λ Tony's blog λ
The weblog of Tony Morris

scala.Option Cheat Sheet

Posted on January 16, 2008, in Programming

Many people who are coming in to Scala first encounter the Option type, which may be thought of (among other things) as a type-safe null. They also encounter pattern matching as both a new and (relatively) powerful concept, but also one that is easy to understand. This leads to quite a lot of use of pattern matching and often excessively so in what I have observed.

Particularly with a type as trivial as Option, it is almost always possible to do away with pattern matching by using a higher-order function. Use of this function is typically preferred over pattern matching as tighter code. In fact, it is important to observe that it is possible to encapsulate all forms of pattern matching over Option with one simple higher-order function:

def option[A, X](o: Option[A])(none: => X, some: => A => X): X = ...

Then, all functions can be written in terms of this one and needn’t pattern match at all. For example, consider Option.map:

def map[A, B](o: Option[A], f: A => B) =
  option(o, None, a => Some(f(a)))

In this post, I am going to give some common uses of pattern matching, which many developers might find themselves performing, followed by the use of a function that already exists on Option that encapsulates that given form of pattern matching. If you find yourself using pattern matching in a form not listed below, but feel it could be abstracted, then chances are that such a function exists in the Scalaz extension to scala.Option.

I will use the identifier foo below to denote any particular function, including many functions composed, for example, foo(x) may represent the composition of two functions f and g: f(g(x)). I also use the identifier option to denote any value of the type scala.Option.

I hope this helps :)


flatMap

option match {
  case None => None
  case Some(x) => foo(x)
}

This code is equivalent to:

option.flatMap(foo(_))

flatten

option match {
  case None => None
  case Some(x) => x
}

This code is equivalent to:

option.flatten

map

option match {
  case None => None
  case Some(x) => Some(foo(x))
}

This code is equivalent to:

option.map(foo(_))

foreach

option match {
  case None => {}
  case Some(x) => foo(x)
}

This code is equivalent to:

option.foreach(foo(_))

isDefined

option match {
  case None => false
  case Some(_) => true
}

This code is equivalent to:

option.isDefined

isEmpty

option match {
  case None => true
  case Some(_) => false
}

This code is equivalent to:

option.isEmpty

forall

option match {
  case None => true
  case Some(x) => foo(x)
}

This code is equivalent to:

option.forall(foo(_))

exists

option match {
  case None => false
  case Some(x) => foo(x)
}

This code is equivalent to:

option.exists(foo(_))

orElse

option match {
  case None => foo
  case Some(x) => Some(x)
}

This code is equivalent to:

option.orElse(foo)

getOrElse

option match {
  case None => foo
  case Some(x) => x
}

This code is equivalent to:

option.getOrElse(foo)

toList

option match {
  case None => Nil
  case Some(x) => x :: Nil
}

This code is equivalent to:

option.toList

coflatMap1

option match {
  case None => None
  case Some(_) => Some(foo(option))
}

This code is equivalent to:

option.coflatMap(foo(_))

duplicate2

option match {
  case None => None
  case Some(_) => Some(option)
}

This code is equivalent to:

option.duplicate

  1. Unfortunately coflatMap is not part of the standard library. You will need to write it yourself or use Scalaz.

  2. Unfortunately, duplicate is not part of the standard library. You will need to write it yourself or use Scalaz.