Michael
Michael

Reputation: 42110

How to apply function to list of options in Scala?

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

Answers (1)

Ben Reich
Ben Reich

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

Related Questions