When I have one Option[T]
instance it is quite easy to perform any operation on T
using monadic operations such as map()
and flatMap()
. This way I don't have to do checks to see whether it is defined or empty, and chain operations together to ultimately get an Option[R]
for the result R
.
My difficulty is whether there is a similar elegant way to perform functions on two Option[T]
instances.
Lets take a simple example where I have two vals, x
and y
of type Option[Int]
. And I want to get the maximum of them if they are both defined, or the one that is defined if only one is defined, and None
if none are defined.
How would one write this elegantly without involving lots of isDefined
checks inside the map()
of the first Option
?
You can use something like this:
def optMax(op1:Option[Int], op2: Option[Int]) = op1 ++ op2 match {
case Nil => None
case list => list.max
}
Or one much better:
def f(vars: Option[Int]*) = (for( vs <- vars) yield vs).max
@jwvh,thanks for a good improvement:
def f(vars: Option[Int]*) = vars.max
Usually, you'll want to do something if both values are defined. In that case, you could use a for-comprehension:
val aOpt: Option[Int] = getIntOpt
val bOpt: Option[Int] = getIntOpt
val maxOpt: Option[Int] =
for {
a <- aOpt
b <- bOpt
} yield max(a, b)
Now, the problem you described is not as common. You want to do something if both values are defined, but you also want to retrieve the value of an option if only one of them is defined.
I would just use the for-comprehension above, and then chain two calls to orElse
to provide alternative values if maxOpt
turns out to be None
.
maxOpt orElse aOpt orElse bOpt
orElse
's signature:
def orElse[B >: A](alternative: ⇒ Option[B]): Option[B]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With