Yesterday I watched Graham Tackley’s talk (slides) on moving from Java to Scala at theguardian. The presentation is well worth watching if you’re considering adding Scala to your project.
One of the highlights for me was to see how easy it is to integrate Scala with the regular Java development and deployment process and how the team’s coding style evolved and improved as their understanding of Scala increased.
Another interesting point was that after a year of using Scala the team’s favorite feature was the Option
type.
Anyone new to Scala will quickly encounter the Option type. An Option[T]
represents a value that may be present (containing Some
value of type
T
) or is not there (None
). Java has a similar facility built right into the language: nulls. So what makes Options so great compared to nulls?
Let’s first start with a simple example. Java programmers moving to Scala may start using Options as follows:
val name: Option[String] = Some("Erik")
if (name.isDefined) // if (name != null) in Java
println("Hello " + name.get + ", how are you?")
else
println("Hello, how are you?")
Basically the only differences with the normal null based solution is that the variable name
is explicitly marked as being optional and we need an
explicit call to the get
method when reading the value from the option. Except for the improved documentation there is not much of an improvement
over plain old nulls.
Fortunately, a Scala Option is defined by the library (not as part of the language specification) and the library provides some very useful additions to make working with Options a lot nicer than with regular nulls. Here’s another way to write the above example:
println(name.map("Hello " + _ + ", how are you?").getOrElse("Hello, how are you?"))
In this case we map
over the contents of the Option. If there is a value, Scala will pass the value contained in the Option to the function we pass
as a parameter to map (in this case a function that returns an appropriate greeting).
Then we use Option’s getOrElse
method to either display the generated message or the default message when the name is not known. Neat!
For people familiar with using map
on collections: you can think of Options as a special kind of collection that can contain at most a single value,
allowing you to use iteration to conditionally run code based on the presence of a value inside the option.
Let’s switch to another example adapted from Graham Tackley’s presentation. Suppose you need to determine the response format based on the HTTP request. Here’s something you could write in Java:
public String negotiateFormat(HttpServletRequest request) {
String format = request.getParameter("format");
if (format == null)
format = getFormatFromUriExtension(request);
if (format == null)
format = getFormatFromAcceptHeader(request);
if (format == null)
format = "html";
return format;
}
The Scala equivalent reduces this to the essence of trying the various options in order and defaulting if no matching option was found:
def negotiateFormat(request: HttpServletRequest) =
request.getParameterOption("format")
.orElse(getFormatFromUriExtension(request))
.orElse(getFormatFromAcceptHeader(request))
.getOrElse("html")
Not only half the amount of code, but also an improvement in readability and with less room for error (inverting an if-condition for example).
Besides basic chaining and defaulting of options, Scala also provides ways to combined multiple Option values into a single value (flatMap
), etc.
When you need to integrate with null-based Java code you can use Option(someValueThatMayBeNull)
to turn a possibly-null value into an option. With
the Option orNull
method you can turn a Scala Option back into a possibly-null value.
When first encountering Option there seems to be little or no difference with regular null based code. But by having the possibilities of “None” made explicit in the APIs and by using the various functions that Options provide code becomes shorter, clearer, and simpler. After a while you start noticing that the number of nulls you have to deal with are greatly reduced, even when programming in Java.