Type safe Scala — Don’t use null
The most dreaded inhabitant.
null
is a special value that denotes a reference that points to nowhere, in other words, it’s the “zero value of the references set”. This value hence inhabits all reference types in Scala and Java. It was first implemented by the great Tony Hoare , and called it afterwards his million dollar mistake.
To me, the problem of null
is not itself but rather how traditional type systems make use of it. To understand why null exists let’s think of an array of string references, and that we want to remove one of the references (for example to avoid loitering) without performing the costly operation of resizing the array, what reference value should we use when replacing the original reference? In this case we need an special reference value that denotes the zero reference, that’s precisely null.
If null is necessary, why is it so dreaded then? Because traditional imperative type systems implicitly bypass the reference layer for the programmer (this is good for the learning curve but bad for avoiding bugs), causing all sort of trouble when the followed reference is null.
A solution would be if type systems made explicit the use of references, instead of letting us write:
They should force us to write:
Because of Scala’s compatibility with Java, we don’t get forced to use an explicit strong reference type, but we still can avoid the null disease by using the Option pattern cure, and the idea is very simple: if we want to express the possibility of absence, we can use something very similar to what we already use for expressing indeterminacy.
For expressing indeterminacy we use lists, defined as:
For expressing possibility of absence we could use also a list, but that’s too unnecessarily powerful (for more information on why that is bad check out Constraints Liberate, Liberties Constrain by Runar Bjarnason), so we better use a list that can only hold one element: Option
.
Once we got that, we can start using it in all places where we don’t have a value to return, for example:
When performing division, instead of returning an Int or fail with an exception when the divisor is zero, we return Option[Int]
:
When indexing a list, instead of returning a value A for that index or fail with an exception when that index doesn’t exist, we return Option[A]
:
Thanks to using Option we have transformed what in the beginning was a Partial function into a Total function. See Partial functions .