Using the Scala Option, Some, and None idiom (instead of Java null)

A powerful Scala idiom is to use the Option class when returning a value from a function that can be null. Simply stated, instead of returning one object when a function succeeds and null when it fails, your function should instead return an instance of an Option, where the instance is either:

  1. An instance of the Scala Some class
  2. An instance of the Scala None class

Because Some and None are both children of Option, your function signature just declares that you're returning an Option that contains some type (such as the Int type shown below). At the very least, this has the tremendous benefit of letting the user of your function know what’s going on.

A simple Scala Option example

Here’s an example of how to use the Scala Option idiom. This source code example is copied from the original version of the book, Beginning Scala:

def toInt(in: String): Option[Int] = {
    try {
        Some(Integer.parseInt(in.trim))
    } catch {
        case e: NumberFormatException => None
    }
}

Here's how this toInt function works:

  • It takes a String as a parameter.
  • If it can convert the String to an Int, it does so, returning it as Some(Int).
  • If the String can't be converted to an Int, it returns None.

If you're a consumer of this toInt function, your code will look something like this:

toInt(someString) match {
    case Some(i) => println(i)
    case None => println("That didn't work.")
}

Why Option is better than null

This may not look any better than working with null in Java, but to see the value, you have to put yourself in the shoes of the consumer of the toInt function, and imagine you didn't write that function.

In Java, if you didn't write the toInt method, you'd have to depend on the Javadoc of the toInt method.

(1) In the first case, if you didn't look at the Javadoc for the Java toInt method, you might not know that toInt could return a null, and your code could potentially throw a NullPointerException.

(2) In the second case, if you did happen to read the Javadoc, and did see that the code could return a null, you might handle it like this:

Integer i = toInt(someString);
if (i == null) {
    System.out.println("That didn't work.");
} else {
    System.out.println(i);
}

That code isn't any worse than the Scala Option and match approach, but you did have to read the Javadoc to know this was needed.

(3) In the third case, the programmer of the toInt function could handle the NumberFormatException differently, and return some other value besides null, in this case, perhaps zero or some other meaningless number.

Even better!

If you're still not sold on using the Option/Some/None pattern instead of using null values -- I know I wasn't completely sold at this point -- let's see where Scala shines.

Let's assume you want to get the sum of a List that contains a bunch of String values, and some of those strings can be converted to Int values, and some can't:

val bag = List("1", "2", "foo", "3", "bar")

Seems like the code should look really ugly, right? Wrong. 

In Scala we can write a "sum" expression in just one line of easy to read code:

val sum = bag.flatMap(toInt).sum

Because (a) we've written toInt to return either a Some[Int] or None value, and (b) flatMap knows how to handle those values, writing this line of code is a piece of cake, and again, it's easy to read and understand.

Now that shows how the Option/Some/None pattern really shines!

Java null versus Scala Option

If you've been through this scenario when using someone else's code, you know that at the very least (a) you need to read their Javadoc, and (b) if you don't, your code might throw a NullPointerException. Compare this to the Scala Option idiom:

  • You can see from the Scala function signature that the code returns Option[Int], and knowing the Option/Some/None idiom, you know how to handle this situation. You can see this signature from your IDE -- there's no need to go look at the Javadoc for the function.

Getting exception information with Scala's Either, Left, and Right

One weakness of the Option approach is that you can't tell why something failed; you can't get access to the error/exception information. A solution to this is to use the Either/Left/Right classes, which are like Option/Some/None, except you can get access to the exception information. See my Scala Either, Left, and Right tutorial to see how to use Either/Left/Right, or the Try/Success/Failure classes introduced in Scala 2.10.

Summary: Scala Option, Some, and None

Even with this simple example, I hope you can see that the Scala Option/Some/None idiom can save you a lot of grief. Although in a simple example like this it doesn't seem to save you any code, I believe your code will be much more readable, and you'll avoid all the problems you can encounter when potentially dealing with null values being returned from functions.