Reputation: 4037
I am working on a simple function that should, given x
, return a tuple (y, z)
such that y <= abs(5) + z * 10 = x
, where z
the smallest possible value.
In C, I would loop over z++
and y++
, until their sum matches x
.
Currently, I am trying to solve this problem functionally. Please consider the following example:
let foo x =
let rec aux (y, z, q) =
match (y + z * 10) with
q -> (y, z)
|_ -> aux(y + 1, z + 1, q) //How to correctly set the increments?
aux(0, 0, x)
This approach always returns (0, 0)
, no matter what. I referred to this question, while thinking a solution. I am aware that mutable variables should be avoided, and that is what I do. Unfortunately, I am afraid I missed the point, somewhere, thus I am approaching the problem from the wrong side.
Upvotes: 2
Views: 309
Reputation: 10624
In F# you are generally either within a value expression or a pattern matching expression. When you do this:
match (y + z * 10) with
q -> (y, z)
You're effectively saying: "Calculate y + z * 10
and then always assign the result to a new variable q
, ignore this new variable and return (y, z)
". This is because q
is written in a pattern matching expression as it's just after with
.
This is also why you're getting a warning on the next line saying "This rule will never by matched". This is a very common misunderstanding when people are learning F#.
You're not really making use of pattern matching at all when you do this. So I would recommend using an if
expression instead:
if y + z * 10 = q
then (y, z)
else aux (y + 1, z + 1, q)
This is actually equivalent to using the ternary operators ?
and :
in C because it's an expression, not a statement, but it reads more clearly.
Upvotes: 1
Reputation: 13577
You're introducing a new q
binding for the result of the expression evaluated in your first case match rather than comparing against it. What you want is something like this:
match (y + z * 10) with
| r when r = q -> (y, z)
| _ -> aux(y + 1, z + 1, q)
Upvotes: 4