F# Conditional Expressions if…then..else returning unit or ()

  • A+

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.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: