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):
int a = 10 + (3 * (return 10; 2));
return a;
Why didn't you get error when you wrote if .. then ()
? The ()
expression creates a value of type unit
that is special, because it has only one valid value. F# allows you to write if .. then
without else
when returning unit
, because it can figure out that the else
branch has to return the only existing unit value, so it sees your code as:
if something then ()
else () // implicitly added by the compiler
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.
F# has no return statement. The only way to do what you want to here, to choose either one block or the other, is with if
.. else
:
let myf (mypar: int) =
if mypar = 2 then
4
else
mypar + 1
Alternatively, throwing an exception exits the function early:
let myf (mypar: int) =
if mypar = 2 then
failwith "invalid argument"
mypar + 1
Have you tried using an else
instead?
let myf (mypar: int) =
if mypar = 2 then
4
else
mypar + 1
I haven't tried it myself, but it's worth a shot :)
(Also consider using pattern matching instead, of course.)
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