I have the following Scala code:
def f(x: Int, y: Int): Option[String] = x*y match {
case 0 => None
case n => Some(n.toString)
}
val data = List((0, 1), (1, 0), (2, 3), (4, -1))
data flatMap {case (x, y) => f(x, y)}
But, the last line is too verbose so I tried all of these and none of them compiles.
data flatMap f
data flatMap f.tupled
data flatMap Function.tupled(f)
data flatMap {f _}
data flatMap (f _).tupled
data flatMap f(_)
What am I doing wrong? The only thing that works is this:
(data map Function.tupled(f)).flatten
I thought a map
followed by flatten
can always be replaced by flatMap
, but although the above line compiles, this does not:
data flatMap Function.tupled(f)
You can only use flatMap
when returning Options
because there is an implicit conversion from Option
to Iterable
by the implicit option2Iterable
. The method flatMap
on your List[(Int, Int)]
expects a function from (Int, Int)
to GenTraversableOnce[Int]
. The compiler is having trouble identifying that implicit conversion as a viable option here. You can help the compiler along by explicitly specifying your generic parameters:
import Function._
data.flatMap[String, Iterable[String]](tupled(f))
//Or
data flatMap tupled[Int, Int, Iterable[String]](f)
Other formulations of the same idea might also allow the compiler to pick the correct types and implicits, even without the explicit generics:
data flatMap (tupled(f _)(_))
data.flatMap (f.tupled(f _)(_))
Finally, you might also want to play with collect
together with unlift
here, which can be a nice way to express this logic as well:
data collect unlift((f _).tupled)
data collect unlift(tupled(f))
Function.unlift
takes a method that returns an Option
and turns it into PartialFunction
that doesn't match where the original function would return None
. collect
takes a partial function and collects the values of a the partial function if it is defined at each element.
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