Reputation: 42110
Suppose I have a function f: (Int, Int, Int) => String
. I can easily apply it to three parameters of type Option[Int]
:
def foo(f: (Int, Int, Int) => String,
ox: Option[Int],
oy: Option[Int],
oz: Option[Int]): Option[String] = ox <*> (oy <*> (oz <*> f.curried.some))
Suppose now that I need to apply f
to the first three elements of list ois: List[Option[Int]]
. For example:
List() => None
List(1.some, 2.some) => None
List(1.some, None, 2.some, 3.some) => None
List(1.some, 2.some, 3.some, 4.some) => Some(f(1, 2, 3))
List(1.some, 2.some, 3.some, None) => Some(f(1, 2, 3))
How would you implement it ?
Upvotes: 1
Views: 660
Reputation: 16324
You could use Option
, take
, flatten
, and collect
together for a pretty clean version:
def foo(f: (Int, Int, Int) => String, ois: List[Option[Int]]) =
Option(ois.take(3).flatten) collect {
case List(a, b, c) => f(a, b, c)
}
ois.take(3).flatten
will only match List(a,b,c)
if the first three elements are Some
. You wrap the variable in Option
to enable the desired collect
semantics (such that the partial function miss will return None
, and the return of the partial function will be wrapped in Some
).
Upvotes: 4