If you want to get a value out of a Scala Option
type, there are a few ways to do it. In this article I’ll start by showing those approaches, and then discuss the approach of using the fold
method on an Option
(which I’ve seen discussed recently on Twitter).
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 likefold
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.
this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |
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.