I'm trying to make a function that compares a tuple with the values of an array of tuples. I need this to return a boolean, but VS2013 keeps telling me: "This expression was expected to have type 'unit', but has type 'bool'"
let compare (i,j,a,(x : (int*int*int) array)) =
for q in 0 .. x.GetLength(0) do
match (i,j,a,x) with
| (i,j,a,x) when (i,j,a) = x.[q] -> true
| _ -> false
Also tried to give the values as two parameters, but it doesn't work either:
let compare (i,j,a) (x : (int*int*int) array) =
for q in 0 .. x.GetLength(0) do
match (i,j,a) with
| x.[q] -> true
| _ -> false
Any help would be appreciated!
To expand a little bit on the answer from Chris, the main reason why your code does not work is that F# is an expression-based language and does not have imperative-style control-flow that you might be expecting here (if you incorrectly read the body of the expression as return
keyword).
As F# is expression-based, everything is an expression that evaluates to a value. So, true
is an expression that evaluates to true (boolean). Pattern matching from your example:
match (i,j,a,x) with
| (i,j,a,x) when (i,j,a) = x.[q] -> true
| _ -> false
... is also an expression that evaluates to true
or false
(boolean value) depending on the values of variables. In this case, conditional would be simpler though:
if (i,j,a,x) = x.[q] then true else false
... or you could just write the condition (i,j,a,x) = x.[q]
which means exactly the same thing. Now, for
loop is tricky, because it evaluates the body multiple times and so it would potentially get multiple return values. For this reason, F# has a special type unit
(think void
in C#) which represents a value that does not carry any information. So, for
loop expects unit
-returning body like:
for i in 1 .. 10 do
printfn "Foo"
You can check that printfn "Foo"
actually returns unit value by writing for example:
for i in 1 .. 10 do
let nothing = printfn "Foo"
nothing
If you place mouse pointer over nothing
, you'll see that it is of type unit
.
So, for
loop is not a good approach if you want to break the iteration in the middle (because it cannot be done in F#). As already mentioned by Chris and Søren you can use functions from the Array
module to easily implement the logic. Alternatively, you would have to write this using recursion or mutable variables - but the Array
module works nicely here.