Tuesday, April 12, 2011

The beauty of Scala's Option/Some/None

Here is a simple feature of Scala that is worth gold.

Take this Java method:
Foo computeFoo() { … }
The implementor of this method may well return an actual object of type Foo, but may also return null.

Usually returning null tells the caller, "well I know I am supposed to return a Foo, but here I just can't return one, so here is null instead, and you deal with it".

There is nothing really wrong with that: there are just cases where you reasonably cannot return a value and need to tell that to the caller.

The issue is that just by looking at the method, you don't know if it can return null. You have to look at the documentation for the method, or its implementation.

Because of this, the caller will often place null checks all over the place, maybe as part of a "defensive programming" strategy. And then, what do you do if the value is null? You have to think about what's reasonable. If the method never actually returns null, it was all a waste and it clogs the code.

If like us you have been burned for 20 years or more with languages that use this kind of paradigm (from C to C++ to Java to JavaScript and others), you might think that this is just a normal way of doing things.

But as a new Scala programmer, you suddenly realize that it is not! And Scala has a nice solution to this problem: the Option class.

In Scala, if you know the method might not return a value, you would write it this way instead:
def computeFoo: Option[Foo] = { … }
Notice the "Option of Foo" return type.

As a user of the function or method, by looking at this function, you know that it may not always return a Foo. So what does it return? This is better shown with pattern matching:
computeFoo match {
  case Some(foo) => … // got a Foo, do something with it
  case None => … // did not get a Foo, deal with it
}
The beauty is that you know that you don't need to do this for methods and functions that do not return an Option. If the method above always returns a value, you would write it in a way very similar to the Java way:
def computeFoo: Foo = { … }
Here, in good Scala land, the caller can assume that the function returns a value, avoid null checks, and gain clarity and confidence in the process.

And of course Option can also be used for parameters to functions, not only as function return values.

Now there is a twist: Scala, I assume for compatibility with the Java ecosystem, also supports null. So nothing actually prevents these methods from returning a null. It's just considered bad practice to do so and to not use the Option/Some/None trio. And if you are calling Java methods, those typically will return null as that is the convention in Java.

But for pure Scala libraries (including the standard Scala library), Java libraries with proper Scala wrappers, and of course your own Scala code, the use of Option/Some/None is the rule and life is good :)

3 comments:

  1. It's a bit of a shift but seems like a nice alternative to null checks. Will certainly try the approach.

    ReplyDelete
  2. Certainly, it's an Either Monad.

    ReplyDelete
  3. You probably mean a Maybe monad, as in Haskell's.

    ReplyDelete