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?
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.
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.
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.
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).
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"
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"
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With