Summary
Functional programming techniques often provide elegant solutions to common problems. In a recent blog post, Daniel Spiewak introduces Scala's Option type, and shows how it can provide a convenient way to return meaningful values from a method.
Advertisement
Methods sometimes compute several interesting results from their input parameters. Yet, many languages, including Java, allow only one return value from a method. It would be convenient to have a built-in language construct that allows the return of more than just a single value from a method call, writes Daniel Spiewak in a recent blog post, The "Option" Pattern.
Spiewak introduces Scala's Option construct, illustrating its use with a common example from Java programming:
Often times a method needs to return either a value or nothing, depending on various conditions. More importantly, some internal state may be uninitialized, so a common “default” value for this state would be null...
Primitive values cannot be valued as null because they are true primitives (an int is actually a bona-fide integer value sitting in a register somewhere at the hardware level)... This too is a holdover from the days of C and C++, but it’s something we have to deal with. One of the consequences of this is that there is no reasonable “non-value” for primitive types... Effectively, null is an untyped value which may be assigned to any class type. Java has no concept of a Nothing type which is a subtype of anything.
In the article, Spiewak describes just such a construct in Scala, Option:
Option is a class in the Scala core libraries. It is what object-oriented developers would call “a simple container”. It simply wraps around an instance of some type as specified in its type parameter...
A simple application would be in a naive integer division function:
def div(a:Int)(b:Int):Option[Int] = if (b <= 0) None
else if (a < b) Some(0)
else Some(1 + div(a - b)(b).get)
What’s really interesting here is the use of Option to encapsulate the result. Here’s how we could use this method to perform some useful(?) calculations:
Each return value is wrapped in an instance of class Some, which is a subclass of Option... This doesn’t seem very useful until we consider what happens when we try to divide values which break the algorithm:
div(13)(0) // => None
div(25)(-5) // => None
Instead of getting an integer result wrapped in an enclosing class, we get an instance of a totally different class which doesn’t appear to encapsulate any value at all. None is still a subclass of Option, but unlike Some it does not represent any specific value. In fact, it would be more accurate to say that it represents the absence of a value.
In the article, Spiewak discusses how to use pattern matching to retrieve values from an Option, and also shows an example of implementing an Option-like construct in Java.What do you think of Scala's Option class?
In cases like this, our Java code usually returns Integer or Boolean and you check for null. (or a special NULL constant) Seems equivalent to returning an Option and checking for None - what's the big deal???
Personally, I prefer primitives that are always initialized to something. Even my Strings are usually initialized to "". Saves a lot of checking for null in equals, hashcode, and other methods. Admittedly, this is not always possible.
"One of the consequences of this is that there is no reasonable “non-value” for primitive types"
For doubles, use Double.NaN I sometimes use -0 (0x8000...) for ints but its not great.
To me, Scala Option can provide a more consistent way of data return from method. You already listed few possible ways of "nothing" cases to check for types like int, String and Object. But for Scala, it's always None. Consistency can be a good help in a language.
Second thing I like Option is it support Scala's pattern matching. It not only matched it, but can extract the value away from the wrapper Some. Here are some examples:
def rand = Math.random*10 toInt def getInput1 = if(rand % 2 == 0) Some(102) else None getInput1 match{ case Some(n)=>println("valid number " +n) case None=>println("invalid number") }
The big deal is twofold. First, in languages that have Java style null there's no way to know if something might be null without checking. Contrast that with Option (or Maybe) types where the compiler tells you when it's necessary to check and when it isn't. Scala programmers have null available with the exact same semantics as Java's null. But for the most part Scala programmers avoid it except when interfacing to existing Java libraries. If you look at Scala code bases you'll see lots of Option/Some/None but very few nulls. That means correspondingly fewer NPEs.
The second has to do with something in functional programming called monads. They're pretty easy once you "get" them but there's an abstraction hurdle to jump over that most people get stuck on for awhile.
"Option" is the standard name in the ML family and Scala is in many ways a closer cousin to ML than it is to Haskell. But either way, it's the same idea. Also, the standard library doesn't have Either yet, but Tony Morris has built one for the scalaz library. He's also built a clean generic monadic library with many of the things you expect from Haskell's Control.Monad.
All that said, Scala is neither Haskell nor ML (nor Java) but it's own unique language with its own unique way of looking at things.
I usually comment my methods to say if they may return null but comments can be wrong, my coworkers aren't as wonderful as me :-) so I agree that Option is more consistent. Maybe some java annotation to enforce this would help. (Also annotations for the params coming in to say whether they may be null)
Agree that long chains of possible nulls are a PITA. There are some ways around them but it requires discipline. I have sometimes written code like this:
For what it's worth, in our internal language (GScript) we expose simple getter/setter pairs as properties, i.e. something like x.getFoo().getBar() becomes x.Foo.Bar. We then have the rule that chained property access expressions return null if any component of the path is null; they don't NPE. If there's a method call in there, then all bets are off (though at least our runtime tells you which subexpression evaluated to null).
That may or not be the right thing, depending on your perspective; the real historical reason for that is that we use paths like that for UI-level binding, so if you want to display the city where a claim took place you might have a path like Claim.Location.City; if the location is null, you just want that field in the UI to be blank rather than blowing out with an NPE that the user or the web framework needs to worry about.
So we think it generally makes the common chained-property/getter case more usable, but it can surprise people.
> For what it's worth, in our internal language (GScript) we > expose simple getter/setter pairs as properties, i.e. > something like x.getFoo().getBar() becomes x.Foo.Bar
> GScript with 'G' like Groovy? :-) > > See: Property access > See: Safe dereference operator > > so in Groovy: y = x?.foo?.bar does exactly what you > wrote.
GScript is kind of like Groovy. The designer decided a while ago that since properties are supposed to have no "real" side effects (whatever that means) it was OK to make all property paths that appear on the rhs of an expression null-tolerant. It's like Groovy's ?. operator, but for free.
I was skeptical at first, but seeing it in action (and not seeing '?.'s all over the code) has made me a believer.
Options are a fine example that it is hard to create a clean language *and* remain compatible with an existing platform :)
If there was no need to interoperate with Java (or JVM in general), null could be abandoned and options used instead. This way, one cannot rely on a non-option value never being null, and that really reduces the usefulness of options. I ran into the same problem with F# and its option types.