Just like many other operations in scala this can be done via for comprehension:
def f(a:Int,b:Int) = a*b
for (x <- maybeX; y <- maybeY) yield f(x, y)
Question
As an example, I want to apply a function f: (Int,Int) => Int
to two elements of type Option[Int]
. My thoughts were something like (a,b).zipped.map(f), but this yields a List, and I want to get a new Option[Int] as result.
scala> def f(a:Int,b:Int) = a*b
f: (a: Int, b: Int)Int
scala> val x = Some(42)
x: Some[Int] = Some(42)
scala> val y:Option[Int] = None
y: Option[Int] = None
scala> (x,y).zipped.map(f)//I want None as a result here
res7: Iterable[Int] = List()
How can this be done without explicitly branching?
La solution
Just like many other operations in scala this can be done via for comprehension:
def f(a:Int,b:Int) = a*b
for (x <- maybeX; y <- maybeY) yield f(x, y)
Autres conseils
As often is the case with this type of question, scalaz has some help:
scala> import scalaz._
import scalaz._
scala> import Scalaz._
import Scalaz._
scala> def f(a:Int,b:Int) = a*b
f: (a: Int, b: Int)Int
scala> val x = Some(42)
x: Some[Int] = Some(42)
scala> val y:Option[Int] = None
y: Option[Int] = None
scala> ^(x,y)(f)
res0: Option[Int] = None
scala> val x = 42.some
x: Option[Int] = Some(42)
scala> (x |@| y)(f)
res3: Option[Int] = None
Using om-nom-nom's idea, I can do something like this:
scala> def f(a:Int,b:Int) = a*b
f: (a: Int, b: Int)Int
scala> def lifted(f: (Int,Int) => Int) = (a:Option[Int],b:Option[Int]) => for(x<-a;y<-b) yield f(x,y)
lifted: (f: (Int, Int) => Int)(Option[Int], Option[Int]) => Option[Int]
scala> def liftedF = lifted(f)
liftedF: (Option[Int], Option[Int]) => Option[Int]
scala> val x = Some(42)
x: Some[Int] = Some(42)
scala> val y:Option[Int] = None
y: Option[Int] = None
scala> liftedF(x,x)
res0: Option[Int] = Some(1764)
scala> liftedF(x,y)
res2: Option[Int] = None
We can even generalize this...please cover your eyes:
def lift2[A, B, C](f: (A, B) => C): (Option[A], Option[B]) => Option[C] = (a: Option[A], b: Option[B]) =>
for (x <- a; y <- b) yield f(x, y)