F#'s Condtional Expressions require a condition to check, a branch for true, and a branch for false. For example:
let x =
if ("hello" = null)
then true
else false //error if else branch missing
However, something gets weird when unit
, aka ()
, is involved.
let y =
if ("hello" = null)
then raise <| new ArgumentNullException()
else () //happy with or without else branch
And more simply:
let z =
if ("hello" = null)
then ()
else () //happy with or without else branch
Why isn't anelse
branch required when unit
is returned?
Consider the following code:
let f a = if a > 5 then true
If you call f 10
, it returns true
.
Now, ask yourself this: what should f 2
return? I know you're going to say false
, but how does the compiler know that? I mean, it's just as likely that you meant it to return true
in both cases, isn't it? Or even, perhaps, crash in the a <= 5
case, who knows?
So in order for the program to be "complete" (i.e. contain instructions for what to do in every situation), you always have to specify an else
branch.
unit
, however, is special.
Returning unit
means that there is no meaningful return value. Essentially unit
stands for side-effect: it means that the thing that returned it was meant to produce some effect in the external world. Since F# is not a pure language, such unit
-returning things are quite ubiquitous. For example, debug logging:
let f x =
if x < 42 then printfn "Something fishy, x = %d" x
x + 5
With such statements, there is no ambiguity: it's always known that the else
branch is meant to return ()
as well. After all, there are no other values of unit
, are there? At the same time, always adding else ()
at the end would be very tiresome and obfuscating. So, in the interest of usability, the compiler doesn't require an else
branch in this specific case.
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