Search code examples
scalapattern-matchingpartialfunction

Collect results of multiple partial functions at single value?


Suppose I have some partial functions that may have overlapping domains:

val funcs: Seq[PartialFunction[Any, Int]] = Vector(
{ case i: Int if i % 2 == 0 => i*2 }
,
{ case i: Int if i % 2 == 1 => i*3 }
,
{ case i: Int if i % 6 == 0 => i*5 }
)

I want to apply them to a value and collect the results for any that are defined at that val. I thought there would be an elegant way to use collect for this but the best I've been able to do is

val num = 66
funcs.collect { case func if func.isDefinedAt(num) => func(num) }
// or 
funcs.filter(_.isDefinedAt(num)).map(_(num))

This doesn't seem clean. Is there some way to use the builtin case mechanism to test definedness and evaluate at the same time, maybe by currying them against the test value or something like that?


Solution

  • Partial functions have a lift method that is Some(res) if the PF is defined and None if not defined. Also with the use of flatMap we can essentially ignore the Nones and grab only the Some values.

    funcs.flatMap { func => func.lift(num) }
    

    Or compressed if you enjoy that sort of stuff:

    funcs.flatMap(_.lift(num))