AFAIK, Option
type will have runtime overhead, while nullable types won't, because Option
time is an enum (consuming memory).
Why not just mark optional references as optional, then the compiler can follow code execution and find whenever it can't more be null
?
Edit: I see I was misunderstood. I understand and agree with the advantages of avoiding null pointers. I'm not talking about arbitrary pointers that accept null
. I'm only asking why not use compile-time metadata, like C# 8's nullable reference types and TypeScript with strict null checks, where default pointers can't be null and there's a special syntax (mostly ?
) to indicate a pointer that can accept null.
Edit 2:
Also, Some
is strange, in my opinion. Implicit conversion would be better. But that a language feature and not relevant.
Best Answer
The purpose of Null Tracking in general (of which Nullable Types are only one of many different forms), is to somehow regain a modicum of safety (and sanity) in languages that have null references.
If you have the chance to eliminate null references altogether, that is a much better solution since the problems that null references cause simply will not exist in the first place. Sir Tony Hoare has famously said that he considers inventing the Null Reference his "Billion Dollar Mistake", which is actually a quite conservative estimate on the total costs that null references have caused until today. If even the person who invented them considers them a mistake, why would you willingly put them in a language?
C# has them because, well, they probably didn't know any better, and now they can't get rid of them because of backwards-compatibility. TypeScript has them because its semantics are based on ECMAScript's, which has them.
The real beauty of an
Option
type, though, is that it is isomorphic to a collection that can only hold from zero to one elements. Dealing with collections is one of the most important parts of programming, and thus every language in the world has powerful collections libraries. And you can apply all of the work that has gone into collections also toOption
types.For example, if you want to execute an action with an option, you don't need to check whether it is defined! Every collection library on the planet has a way of iterating over a collection and executing an action for each element. Now, what does "executing an action for each element" mean for an
Option
? Well, if there is no element, then no action is executed. And if there is one element, then the action is executed once with that element.In other words,
foreach
acts exactly like aNULL
check! You can just blindly doand it will print out the value contained in the
Option
if it exists and do nothing if it doesn't exist. The same applies when you want to perform a computation with the value. Every collections library on the planet has a way of iteration over a collection and transforming each element. Again, for anOption
"transforming each element" translates to "transform the value or do nothing". So you can just doAlso, collections libraries have ways to flatten nested collections. Imagine you have a long chain of references, each of which could be
NULL
, and you wanted to access the last reference in that chain. With nestedOption
s, you just writeAnd if you want to get a value out of an
Option
, then you can simply writeand you will either get the value inside the option if it exists, or a default value of your choosing if it doesn't.
The only reason, really, for you to explicitly check for the existence of an
Option
is if you want to do something completely different in case the value is missing.It turns out that
Option
is actually even more than "just" a collection. It is a monad. Languages like C#, Scala, and Haskell have built in syntax sugar for working with monads, and they have powerful libraries for working with monads. I will not go into details about what it means to be a monad, but e.g. one of the advantages is that there are some specific mathematical laws and properties associated with monads, and one can exploit those properties.The fact that Java's
Optional
is not implemented as a monad, not even as a collection, is a significant design flaw, and I think is partially to blame for people not understanding the advantages ofOption
s, simply because some of those advantages cannot be realized with Java'sOptional
.There is also a more philosophical reason for choosing an
Option
type overNULL
references. We can call this "language democracy". There is a major difference between those two:NULL
references are a language feature whereasOption
is a library type.Everybody can write a library type, but only the language designer can write a language feature. That means that if for my code, I need to handle the absence of values in a slightly different manner, I can write a
MyOption
. But I cannot write aMYNULL
reference without changing the language semantics and thus the compiler (or, for a language like C, C++, Java, Go, ECMAScript, Python, Ruby, PHP with multiple implementations, every single compiler and interpreter that exists, has existed, and will ever exist).The more the language designer moves out of the language into libraries, the more the programmers can tailor the language (really, the library) to their needs.
Also, the more the language designer moves out of the language into libraries, the more the compiler writers are forced to make library code fast. If a compiler writer figures out some clever trick to make
NULL
references fast, that doesn't help our hypothetical programmer who has written their own abstraction. But if a compiler writer figures out some clever trick to makeOption
fast, it is highly likely the same trick will also apply toMyOption
(andTry
,Either
,Result
, and possibly even every collection).Take Scala, for example. Unfortunately, because it is designed to interoperate and integrate deeply with the host environment (the Java platform, the ECMAScript platform, there is also an abandoned CLI implementation), it has
null
references and exceptions. But, it also has theOption
type which replaces the former andTry
which replaces the latter. AndTry
first appeared in a library of helpers released by Twitter. It was only later added to the standard library. Such innovation is much harder to do with language features.I can write my own Scala
Option
type, and I don't need to change the compiler for it:Try it out here.