scala-logo-small

Does Scala Have a Null-Coalescing Operator?

Most languages allow null values but then don’t provide good features for handling them. Java is one such language even though Java applications are notorious for having ubiquitous NullPointerExceptions.

Other languages provide different features for null handling. One such mechanism is the null coalescing operator found in C#, Clojure, Swift, and more. The null coalescing operator allows a safe default value to be assigned/returned/etc. in the event that a variable is null.

This is the code example from Microsoft’s C# documentation:

  // C#
  // Set y to the value of x if x is NOT null; otherwise,
  // if x = null, set y to -1.
  int y = x ?? -1;

Scala takes a functional approach instead of providing a null-coalescing operator. It has a disjoint union type Option to represent the presence or absence of a value in a type-safe way. Any Option[A] may be either one of its subtypes: Some or None. If it is a Some, it has methods like “.getOrElse(someDefaultValue)” to allow retrieval of the contained value, which is of type A.

  // Scala
  // in this example "xOption" is of type Option[Int].
  // Set y to the value of x if xOption is a Some(x); otherwise,
  // if xOption is type None, set y to -1
  val y = xOption.getOrElse(-1) 

Option types are explained in Programming in Scala section 15.6.

The main advantage to this approach is that it gives the programmer a compile-time way to represent optional values. And that allows pure Scala applications to have some guarantees that there won’t be any null values at runtime. Furthermore, the standard Scala libraries use Option types in places where it makes sense, such as Map’s “get” method:

  val m = Map() // empty map
  m.get("malcolm") //returns None 

But the disadvantage is that when Scala applications use Java libraries, these guarantees don’t exist. Instead, Scala developers have to remember to make an arguably clumsy conversion from null to the Option type whenever calling library methods that might return null. For example:

  // Scala
  val m = new java.util.HashMap[String, String]() // since this is empty
  val n = m.get("malcolm") // this is null
  val nOption = Option(n)  // but wrapping the null in Option() transforms it to None

Therefore, Scala provides the same result as a null-coalescing operator with “Option(x).getOrelse(-1)” syntax like this:

  val s: String = Option(m.get("malcolm")).getOrElse("Not found in map")

…and it also provides a rich set of functionality related to the Option type.

For those who really, really, really want a null-coalescing operator, the following simple implicit can be defined:

implicit class Coalescer[A](val a: A) extends AnyVal {
  def ??(default: A): A = { Option(a).getOrElse(default) }
}

In which case, this can be done:

  val s = m.get("malcolm") ?? "Not found in map"

…and the value of s will be “Not found in map.”

Leave a Reply

Your email address will not be published. Required fields are marked *