Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I compare x and y in F#?

I need help with the matching pattern that would compare 2 numbers. Something like that:

let test x y =
   match x with
   | y when x < y -> printfn "less than"
   | y when x > y -> printfn "greater than"
   | _ -> printfn "equal"

Somehow it falls to the "_" case when x is 0 and y is 200. What am I doing wrong here?

like image 959
Trident D'Gao Avatar asked Sep 06 '13 03:09

Trident D'Gao


People also ask

What is difference between Y and F x?

Functions are different in a key way from equations: a function is an output. An equation is a relationship between variables. Yes, y=x+3 and f(x)= x+3 yield the same results, which is why we teachers always tell you to remember that 'y and f(x) are the same thing'. However f(x) isn't a variable, but an output.

What does it mean to compare two functions?

Sometimes a problem asks us to compare two functions which are represented in different ways. For example, you might be given a table and a graph, and asked which function is greater for a particular value, or which function increases faster. Example : Two functions are represented in different ways.

Is F of X the same as Y?

Remember: The notation "f (x)" is exactly the same thing as "y". You can even label the y-axis on your graphs with "f (x)", if you feel like it.


4 Answers

The problem with your code is that when you write:

match x with 
| y when x < y -> (...)

.. it means that you want to assign the value of x (the <expr> in match <expr> with) to a new variable named y (the <pat> in | <pat> when ...) and then compare this new y (which now contains the value of x) with the value of x - and so this will always return false. You can always rename the bound variable, so your code is the same as writing:

match x with 
| newY when x < newY -> (...)

Now you can see why this never matches - because you are just comparing x with itself!

Pattern matching is especially useful if you have inputs of some more complicated structure - like tuples or discriminated unions, lists, arrays, option types etc. But if you simply want to compare numbers, it is much easier to just use if:

let test x y =
  if x < y then printfn "less than"
  elif x > y then printfn "greater than"
  else printfn "equal"

In your match, you do not really need to bind any variables - but the solution by John demonstrates how you can make that work - it simply says, take variables x and y and assign them to new variables x and y (which just have the same name).

like image 172
Tomas Petricek Avatar answered Oct 17 '22 08:10

Tomas Petricek


A better version would be to pattern match on both numbers like so

let test x y =
   match (x,y) with
   | (x,y) when x < y -> printfn "less than"
   | (x,y) when x > y -> printfn "greater than"
   | _ -> printfn "equal"
like image 23
John Palmer Avatar answered Oct 17 '22 09:10

John Palmer


If you consult with Pattern Matching (F#) upon what type of pattern matching you use, then it would be so-called variable pattern, where new variable y within the match cases will be assigned the value of match expression x. As this y variable inside match statement shadows the original function parameter y, in the first and the second cases y would be simply getting value of x, hence when guards both fail. Then, the third catch-all match case _ kicks in, so you get "equal" return, as observed.

You can better see what happens if you explore the following snippet:

let f x y =
    match x with
    | y -> y

and try it with something like f arg1 arg2; f will be always returning arg1 regardless of arg2 value.

You may express your original intent still using matching with constant pattern by moving argument comparison into match expression:

let test x y =
    match sign (Operators.compare x y) with
    | 1 -> "greater than"
    | -1 -> "less then"
    | _ -> "equal"
like image 22
Gene Belitski Avatar answered Oct 17 '22 10:10

Gene Belitski


Similar to John Palmer's answer. I think writing it like this will improve your understanding of what is happening:

let test x y = 
    match (x,y) with
    | (a,b) when a < b -> printfn "less than"
    | (a,b) when a > b -> printfn "greater than"
    | _ -> printfn "equal"

In plain terms, when you use a Match statement, the terms in the pattern (i.e. the part before the ->) declare new identifiers. When you re-use y in your pattern, you are hiding the previous identifier y and creating a new one which has the same value as the thing on which you are matching, in this case the identifier x. In other words, you are always comparing the value of x to itself. As others have noted, this is probably best done with an if statement.

like image 3
N_A Avatar answered Oct 17 '22 08:10

N_A