Learn How To Use Option - Avoid Null
Overview
In this tutorial, we will show how to use Option, Some and None.
If you have used other programming languages in the past such as Java or .NET, I'm pretty sure that you must have seen your share of NullPointerException!
By making use of Option, Some and None, Scala encourages you to write functions with no side effects as we've described in the Scala Features tutorial. As a result, all your headaches with NullPointerException should go away :)
Steps
1. How to use Option and Some - a basic example
Let's declare a simple String called glazedDonutTaste. But instead of its type being just a String, you will declare it as an Option of type String using the syntax Option[String]
.
You can then assign its value using the Some class and pass in your donut taste String of Very Tasty.
println("Step 1: How to use Option and Some - a basic example")
val glazedDonutTaste: Option[String] = Some("Very Tasty")
println(s"Glazed Donut taste = ${glazedDonutTaste.get}")
You should see the following output when you run your Scala application in IntelliJ:
Step 1: How to use Option and Some - a basic example
Glazed Donut taste = Very Tasty
NOTE:
- Because we have wrapped our String into an Option, to retrieve its value we call the get() function as shown above.
- But calling get() in a production system is generally a code smell as you may end up with the same NullPointerException.
2. How to use Option and None - a basic example
Let's use another variable called glazedDonutName which is also an Option of type String. But instead of initializing it to a String which is wrapped up into a Some class as shown in Step 1, let's set its value to None.
println("\nStep 2: How to use Option and None - a basic example")
val glazedDonutName: Option[String] = None
println(s"Glazed Donut name = ${glazedDonutName.getOrElse("Glazed Donut")}")
You should see the following output when you run your Scala application in IntelliJ:
Step 2: How to use Option and None - a basic example
Glazed Donut name = Glazed Donut
NOTE:
- We've used the handy getOrElse() function from the Option to supply a default value.
- If you were to call the get() function as shown in Step 1, you will get the exception
java.util.NoSuchElementException: None.get
. - At this point, you may be asking yourself that this exception is similar to your NullPointerException.
- And you are absolutely right! But Pattern Matching is your friend :) let's look at Step 3 below.
3. How to use Pattern Matching with Option
Feel free to review the two previous tutorials Pattern Matching and Tuples.
You've already seen from Step 2 that you can use the getOrElse() function to get a default value in case your variable had no data.
But you can also use Pattern Matching as shown below:
println("\nStep 3: How to use Pattern Matching with Option")
glazedDonutName match {
case Some(name) => println(s"Received donut name = $name")
case None => println(s"No donut name was found!")
}
You should see the following output when you run your Scala application in IntelliJ:
Step 3: How to use Pattern Matching with Option
No donut name was found!
NOTE:
- Sure, you can argue that we have not achieved much!
- But, let's take a pause and assume that you were calling some function to populate your variable glazedDonutName
- As a consumer of that function call, you would not know that the function could potentially return null.
- What have we learned? It's all about intent!
- By being explicit that such a function will return an Option, any consumer of the function can avoid NullPointerException by using getOfElse() or Pattern Matching.
- Not to worry, we will see examples of functions which return Option in upcoming tutorials.
Summary
In this tutorial, we went over the following:
- How to use Option and Some
- How to use Option and None
- How to use Pattern Matching with Option
Tip
- You can use the map() function as a more elegant way of filtering out None.
println("\nTip 1: Filter None using map function")
glazedDonutTaste.map(taste => println(s"glazedDonutTaste = $taste"))
glazedDonutName.map(name => println(s"glazedDonutName = $name"))
You should see the following output when you run your Scala application in IntelliJ:
Tip 1: Filter None using map function
glazedDonutTaste = Very Tasty
NOTE:
- Notice that glazedDonutName was not printed as its value was None
- If the map() function is completely new to you, don't worry we will see more examples when we get to the tutorials on functions.
Source Code
The source code is available on the allaboutscala GitHub repository.
What's Next
In the next tutorial, I will go over the type hierarchy in Scala.