收集单个值下多个偏函数的结果



假设我有一些可能有重叠域的部分函数:

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 }
)

我想将它们应用于一个值,并收集在该val定义的任何结果。我认为有一种优雅的方式来使用collect,但我能做的最好的是

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

这看起来不干净。是否有一些方法可以使用内置的用例机制来测试定义性并同时评估,也许是通过对测试值或类似的东西进行curry ?

偏函数有一个lift方法,如果定义了PF则为Some(res),如果没有定义则为None。同样,使用flatMap,我们基本上可以忽略None,只获取Some的值。

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

或者压缩,如果你喜欢这种东西:

funcs.flatMap(_.lift(num))

同时测试定义性和评估

那是applyOrElsecollectlift使用它来避免双重求值。

这个递归版本表示,应用下一个函数并使用它来构建结果,或者继续构建结果的其余部分。

def f(ff: List[PartialFunction[Any, Int]]): List[Int] = ff match {
  case hd :: tail => hd.applyOrElse(num, (_: Any) => return f(tail)) :: f(tail)
  case _ => Nil
}

这是我第一次在Scala中使用return。我不得不在索引中查找。

这个手工构造避免了在Lifted, Option和适应Option中创建一些对象。

scala> :pa
// Entering paste mode (ctrl-D to finish)
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 }
)
val num = 66
def f(ff: List[PartialFunction[Any, Int]]): List[Int] = ff match {
  case hd :: tail => hd.applyOrElse(num, (_: Any) => return f(tail)) :: f(tail)
  case _ => Nil
}
// Exiting paste mode, now interpreting.
funcs: Seq[PartialFunction[Any,Int]] = Vector(<function1>, <function1>, <function1>)
num: Int = 66
f: (ff: List[PartialFunction[Any,Int]])List[Int]
scala> f(funcs.toList)
res0: List[Int] = List(132, 330)
scala> funcs flatMap (_ lift num)
res1: Seq[Int] = Vector(132, 330)

第二个版本只是使用了一个标志来表达同样的意思。

scala> :pa
// Entering paste mode (ctrl-D to finish)
def f(ff: List[PartialFunction[Any, Int]]): List[Int] = ff match {
  case hd :: tail =>
    var ok = true
    val x  = hd.applyOrElse(num, (_: Any) => { ok = false ; 0 })
    if (ok) x :: f(tail) else f(tail)
  case _ => Nil
}
// Exiting paste mode, now interpreting.
f: (ff: List[PartialFunction[Any,Int]])List[Int]
scala> f(funcs.toList)
res2: List[Int] = List(132, 330)

相关内容

  • 没有找到相关文章

最新更新