Scala Tutorials Part #16 - The Option type
Originally Posted On : 10 May 2017 Last Updated : 18 Oct 2017
The Option Type
Java programmers would be familiar with the
NullPointerException which pops up when you access an object instance
which has not yet been created yet.
This issue is not because of the Java library or the runtime, but it’s because of programmers writing crappy code. A language can offer some level of defense against human stupidity and that is what differentiates languages. Take a look at Null References : The Billion Dollar Mistake
Scala addresses this issue with the Option type. Let’s jump right in.
This is part 16 of the scala tutorial series. Check here for the full series.
- First line of defense in variables
- Introduction to the Option type
- Creating our own Option type
Recall from the first chapter that variables can’t be just declared and left un-initialized.
But that does not prevent what java programmers have been doing all the time, i.e just leave them as
This would result in the dreaded
NullPointerException. We are still exposed to this issue which in medium/large code bases becomes very difficult
to track . Assigning
null to objects is often misused in imperative environments.
null in the scala language exists only for inter-operation with the java language environment. There is a better way to do this.
Option is not a type per se, it is syntactic sugar to a class that is underneath it.
In fact it is an abstract class which has two children
None. These three are not present in the
scala type system hierarchy at all. Let’s take a look at how they work
with a real world example.
Let’s try add data to an null
This would obviously lead to an exception.
Exception in thread "main" java.lang.NullPointerException at JavaRunner.main(JavaRunner.java:9)
If you are developing a customer facing application with some sort of a UI, throwing this error back to it would be absurd. What we would generally do is to catch this exception and then return some sort of a meaningful error message such as the “list not initialized” or something depending on the application.
This is handled in a completely different way in scala.
List is not exactly equal to a java
ArrayList, but for demonstration purposes this should be fine. What we are trying to do is to find the first value
that is greater than 100 and also the first value greater than 1000. Since we have a value that is greater than 100, the list returns the value
by wrapping it into a
Some type. In the case where there is no value greater than 1000 then return
Some which indicates the presence of a value of some type,
None indicates non-existent values.
None should not be confused with
Unit type which is used to represent the absence of a type itself.
This facility is of course provided by the
List collection in scala, but we can build our own if we want to.
At this point, a typical java programmer would have a question in mind like “How do I declare a variable and not initialize it?”
and the simple answer it to that is “You don’t”. You change your programming style not to include un-initialized variables in the code
and not initialize them to
null as well. We will be dealing with the latter part of it i.e
null handling, the former part which is
“Declaring a variable and initializing the variable along with the declaration” style as already seen in
part 1 was a design choice taken by the scala language developers themselves.
Let’s consider a case class
Now there is a situation where we disallow email IDs belonging to gmail and yahoo domains.
The method splits the string using the
@ character and gets the second index from the split array which gives the domain of the email address.
This is now checked with the banned domains list and if there is a match then we return
None else we return a
Below code example which consumes this method should make it clear.
We feed the
User object to the
getFilteredEmailID method which returns an
It can be either
None depending on the computation. This is why
Option is an abstract class since the result is either
None but never an
Option itself at the top level.
Some is a case class and
None is a case object underneath.
What we are doing above is called pattern matching. We will see in detail about what pattern matching is in later tutorials.
For now, it can be visualized as a simplified version of switch statements. The real advantage lies in everything being compile time and there is
no possibility of a runtime
A more simpler way to consume
Option is to use the built in
None is returned then “Banned domain” is printed else the given email ID is printed. This can be used in simpler situations whereas
pattern matching can be used in complex situations.
There are other ways in which an
Option can be consumed, we will take a look at them at appropriate places in our journey through scala.
We saw the usage of the
Option type in a very brief manner. There are several advantages of using the Option/Some/None pattern over java’s
The main reason is you cannot say in a concrete manner when a
NullPointerException will come since it is at runtime.
Although you can carefully profile your code. In reality large code bases make this task tedious and not feasible. When using Scala’s
you can precisely reason that it can be either
None and we can deal with it rather than raising an exception and then catching it.
Option type and its supporting classes
None can also be used to deal with situations other than null pointers. It is otherwise
known as a monadic container which we will see more about in later tutorials.
For a spoiler on the upcoming tutorials, we will see how the unapply method works which is the opposite of apply method and then extractors finally leading to pattern matching.