Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct way to work with two instances of Option together

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?

like image 746
jbx Avatar asked Nov 10 '15 17:11

jbx


2 Answers

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
like image 81
Alexandr Dorokhin Avatar answered Oct 02 '22 18:10

Alexandr Dorokhin


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]
like image 24
dcastro Avatar answered Oct 02 '22 17:10

dcastro