I have a problem when returning values in complex functions. Examples are always better:
Consider the following function:
let myf (mypar: int) =
mypar + 1
Well no probel here, this function is compiled correctly and the signature is:
val myf: int -> int
OK, well. Now consider this code:
let myf (mypar: int) =
if mypar = 2 then
4 (* ERROR *)
mypar + 1
This does not work:
This expression was expected to have type unit but here has int
This error is raised everytime I try to return from my function when I am inside a if
, a while
a for
or every other block. I thought that the problem was assuring that all possible return paths return the same type, but here I do not understand what happens.
Please note that if I insert a ()
unit everything works for example:
let myf (mypar: int) =
if mypar = 2 then
() (* No error *)
mypar + 1
But that unit does not make my function return!!! it continues!!! Furthermore, could you please explain me how F# handles this???
Thankyou
To add some more details, the problem with your approach is that everything in F# is an expression. This makes it a lot easier to reason about your programs (because you don't need to keep track of the currently executing statement), but it means that you always have to write a complete expression.
If you try to write something like
return
, it would be as if you wrote the following in C# (This probably explains why F# doesn't allow this kind of things):Why didn't you get error when you wrote
if .. then ()
? The()
expression creates a value of typeunit
that is special, because it has only one valid value. F# allows you to writeif .. then
withoutelse
when returningunit
, because it can figure out that theelse
branch has to return the only existing unit value, so it sees your code as:The only difference is throwing an exception (using
raise
) which behaves just like in C#. You could break out of a function using exception, but it is much better idea to rewrite the code to have a complete valid expression.