Scala: How to use fold on an Option (syntax, examples)

If you want to get a value out of a Scala Option, there are a few ways to do it. I’ll show those approaches in this article, and then discuss the approach of using the fold method on an Option.

Directly extracting the value out of the Option

A common way to extract the value out of an Option is with a match expression:

val res = option match {
    case Some(i) => i
    case None => default
}

You can also use getOrElse:

val res = option.getOrElse(default)

Applying a function while extracting the value from the Option

If you want to get the value out of an Option while also applying a function to the value, you can again use a match expression:

val res = option match {
    case Some(i) => f(i)
    case None => default
}

You can also use map followed by getOrElse:

val res = option.map(f).getOrElse(default)

Finally, an approach I’ve seen discussed recently is that you can also call fold on the Option:

val res = option.fold(default)(f)

That code applies the function f to the value if the Option is a Some; but if the Option value is actually a None, it returns the default value.

Discussion: Using fold on Option

As I discuss in my tutorial on using fold and reduce in Scala, this use of fold is somewhat consistent with using fold on sequential collections, where fold takes an initial seed value and a folding function. In the example above you can think of the default value as being the seed value:

val res = option.fold(default)(f)

In this example, if option is a None, the default value is returned, and the function f is ignored. Alternatively, if option is a Some, default is ignored, and the function f is applied to the option value. A small but concrete example looks like this:

def f(i: Int) = i + 1

val a = Some(1)
val b = a.fold(0)(f)   // result: b = 2

In this regard this doesn’t feel like the usual use of fold, but the syntax of supplying a value in the first parameter list and a function in the second parameter list is consistent with using fold on a sequential collection.

How fold works on a sequential collection

As a quick example of what I mean about how fold works on a sequential collection, here are a few examples in the Scala REPL. This is how fold works on a list that has values in it, which is analogous to calling fold on a Some:

scala> val x = List(1,2,3)
x: List[Int] = List(1, 2, 3)

scala> val y = x.fold(10)(_ + _)
y: Int = 16

As shown, fold uses both the default value and the folding function, which isn’t consistent with how fold works on an Option (specifically on a Some).

Next, this is how fold works on an empty list, which is analogous to calling fold on a None:

scala> val x: List[Int] = List()
x: List[Int] = List()

scala> val y = x.fold(10)(_ + _)
y: Int = 10

In this case this feels similar to using fold on a None, because both approaches use the seed value, and since there’s nothing in the Option or List, the folding function isn’t really used.

More information

For more information on using techniques like this, see my Using higher-order functions with Option tutorial. In that article I show this fold technique along with many other higher-order functions that are available on the Scala Option type.

... this post is sponsored by my books ...