Optional Is the New Mandatory
Since the beginning of the “computer programming era”, developers had searched for a solution for one of the biggest mistake made in computer science, the invention of the null reference. Since functional programming became mainstream, a solution to this problem seems to arise, the use of the optional type. In this post, I will analyze how this type is used in different programming languages, trying to understand the best practices to apply in each situation.
Returning the nothing
Let’s start from a concrete example. Think about a repository that manages users. One classic method of such type is the method
def findById(id: String): User, whatever an
id could be. This method returns the user that has the given id, or nothing if no such user exists in your persistence layer.
How can we represent the concept of nothing? It is common to use the null reference to accomplish this task.
The problem is not in returning a null reference itself. The problem is using a reference containing a
null. The above code, written in Scala, rises a
NullPointerException during the access of the methods
surname if the
user reference is equal to
So, what’s a possible solution? A first attempt can be to return a
List[User]. The signature of the method becomes the following,
def findById(id: String): List[User]. An empty list means that there is no
user associated with the given
id. A not empty list means that there is a user associated with the given
problem is that the user is exactly one, whereas the semantic of lists if to store zero or more elements.
So using a list seems to be convenient, but not semantically correct. The use of an empty list to represent the nothing produces programs that are hard to read (violating the Principle of least astonishment) and to maintain.
However, the idea behind the use of lists is perfect. How can we refine it?
The Option type
The answer to our question is in the type that Scala calls
Option. Other programming languages call this type in different ways, such as
Optional in Java, or
Maybe in Haskell.
Option[T] type is just like a list that can be empty or can contain exactly one element. It has two subtypes that are
Some[T]. So, an
Option object that contains something is an instance of the
Some[T] subtype, whereas an empty option is an instance of
None. There is only one instance of the
None type that in Scala is defined as an
Option is indeed an Algebraic Data Type, but the definition of such a concept is behind the scope of this post.
It is possible to use the factory method
Option(value: T), declared in the
object to build a new instance of an
Option class. The factory method will create a new
Option instance: If
value is equal to
null, then the
None object is returned,
Option type, our previous method changes its signature in
def findById(id: String): Option[User]. Ok, interesting. However, how can I use the user value contained inside the option type? There are many ways to do that. Let’s look at them.
Getting the value out of the option type
One of the possible choices is to try to get the value out of the option. The API of the
Option type lists the methods
get. The first check if an option contains a value, and the second allows you to extract that value. The usage pattern raising from the use of the above methods is the following.
Despite the use of a
var reference, the above pattern is to avoid. If you call the
get method on a
None object, you will obtain an error at runtime. So, you don’t improve the code that much from the version that checks for the
For this reason, the Scala
Option type provides a variant of the
get method, which is
getOrElse. This method allows you to provide a default value to return in case of an empty option. Imagine that our
User type provides a
gender: Options[String] method, which eventually returns the gender of a user. It is possible to use the following safer pattern using
Using pattern matching
In Scala, it is possible to use pattern matching on Algebraic Data Types. The
Option type is not an exception in this sense. Although it is not such idiomatic, this approach does what it promises us — raw and straightforward.
Using pattern matching is a little more verbose than using the next approach I am going to show you, but it is still more elegant than checking the existence of a value using the
Using the Option type as a list
The suggested approach by the Scala community is to use the
Option type, just as if it was a list. This approach takes advantage of the fact that the
Option type is indeed a monad (also, in this case, explaining what a monad is in functional programming is behind the scope of this post).
Option type, like lists, exposes a lot of useful methods to transform e manage the
Option inner value, without even the need to extract it. Among the others, such methods are the
map method allows you to transform the value owned by an
Option object if any.
flatMap method allows you to compose functions that in turn, return an object of type
filter method allows you to discard any value that does not fulfil a given predicate.
All the above methods, if invoked on a
None object, return
None automatically, preserving any method call concatenation.
Note that we can combine the use of the
filter method using for-comprehension, giving to our code a look more like Haskell.
The above code can be rewritten using a simple
Last but not least, if you need to apply some side-effects if a value is present in an
Option object, you can use the
foreach method. This function cycles on the single value of the option, if present, and executes a procedure.
Option type in other languages
Option type is not present only in Scala. Many programming languages widely use it.
Since Java 8, the language introduced the
Optional<T> type in the mainstream JVM language. It is very similar to its Scala cousin.
Also, the Java API defines different factory methods to build a new instance of
Optional.of which throws an exception if the given value is
Optional.ofNullable, that returns an
Optional.empty in case of
A small difference if the behaviour of the
map method. If the function used by
map returns a
null value, the method interprets this as the
Optional.empty value. The
map method behaves like the
flatMap method, in this particular case.
The above code returns an
Optional.empty value if the name of the user is equal to the
"Riccardo". However, as some Reddit user pointed out, the above approach is no recommended in Java. Use the following code instead.
Another interesting method of the Java
Optional type is
orElseThrow. This method allows us to choose which exception to rising in case of an empty
It worth reporting the answer that Brian Goetz gave to the StackOverflow question, Should Java 8 getters return optional type?.
Optional.getunless you can prove it will never be
null; instead use one of the safe methods like
ifPresent. In retrospect, we should have called get something like
getOrElseThrowNoSuchElementExceptionor something that made it far clearer that this was a highly dangerous method that undermined the whole purpose of Optional in the first place. Lesson learned.
The Kotlin programming language does not have built-in support for something similar to the Scala
Option type or the Java
Optional type. The reason why is mainly that the language support compile-time null checking.
In Kotlin every type has two variants. Continuing our previous example, Kotlin defines both the
User, and the
User? type. A reference of the first type cannot be
null, whereas an instance of the
User? type can also hold the
null value. Any non-nullable type is a child type of the corresponding nullable type.
In other words, Kotlin attempts to solve the problem by forcing you to handle null references. Kotlin forces you to handle the exception or to take full responsibility. For example, you can’t use the dereferencing operator, the
. (dot), if you are managing nullable type. The following code won’t even compile.
Kotlin tries to prevent
NullPointerException for you. The safe call operator,
?. must be used in this case. It checks if the reference is
null, and if it is not, it calls the method on it, propagates the
null value otherwise.
The power of the safe call operator shines with chained methods calls. In this case, it also reminds very strictly the use of the methods
flatMap defined in the
The above method is equal to the following Java counterpart.
If you don’t mind about NPEs, you can always use the
!!. operator, that does not perform any check on reference nullability.
Finally, also Kotlin defines the same behaviour of the
orElse method in Scala or Java for nullable types, using the Elvis operator,
?:. If we want to return a particular value of the gender if something is
null during the gender resolution process, we can proceed as the following code shows.
As you can see, the type of the last
maybeTheGenderOfANoRiccardo variable is not nullable anymore, because the elvis operator eliminates the possibility for the reference to be
In this post, we analyzed a modern solution to deal with the
null value and in general, the absence of information. We started to see how the Scala programming language defines
Option[T] type, listing the best practice of its use. Then, we saw how the good old Java approaches to the problem, the
Optional<T> type, concluding that it is very similar to the solution proposed in Scala.
Finally, we looked at a different solution, the one proposed by Kotlin. Kotlin does not have any optional type, because it tries to handle the nullability of references at compile-time. Although this approach is exquisite and as powerful as the approaches proposed in Scala and Java, it poorly composes with the other constructs used in functional programming. For this reason, Kotlin has its library for functional structures, such as the optional type, which is ARROW.
Bonus: Are you planning to use an option value as a parameter for a method? Please, don’t do that (Why should Java 8’s Optional not be used in arguments).