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

If you want to get a value out of a Scala Option type, 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 (which I’ve seen discussed recently).

1) Getting the value out of an Option, with a backup/default value

As a first look at getting values out of an Option, a common way to extract the value out of a Scala Option is with a match expression:

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

When your goal is to get a value out of an Option or else use a backup/default value, you can also use getOrElse:

val res = option.getOrElse(default)

2) Applying a function to an Option value

Next, 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
}

For this situation you can also use map followed by getOrElse:

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

Using ‘fold’ instead

Finally, this leads to an approach I’ve seen discussed recently, i.e., 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.

If you use fold all the time this may be something that you can read easily, but because I don’t, I prefer either of the first two approaches, but that’s just IMHO. (The reason I don’t like fold is because it takes me too long to think about how it works in this situation.)

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 (a) an initial seed value and (b) 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 some = Some(1)
val res  = some.fold(0)(f)        // res == 2

val none = Option.empty[Int]
val res  = none.fold(0)(f)        // res == 0

As mentioned, I’m not sold on this technique, but I wanted to show it, because other people may like it.

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.