我正在使用一些返回Options的函数,但是我想用PartialFunctions替换它们以便在Scala中使用collect函数。详细地说,我试图通过以下方式在包含部分函数的对象列表上调用collect(和collectFirst):
class A(val bs : List[B]) {
def getAll(i : Int): List[Int] = bs.map(_.foo(i))
}
class B(val y : Int) {
val foo : PartialFunction[Int, Int] = {
case x if x > y => y
}
}
如果为bs中的所有值定义了函数foo,上面的代码将编译并执行我想要的操作。
val a = new A(List(new B(1), new B(2), new B(3)));
println(a.getAll(5))
打印"列表(1,2,3)和#34;但是如果没有为值定义foo,我当然会遇到错误。因此,我想用"收集"
替换它def getAll(i : Int): List[Int] = bs.collect(_.foo(i))
在我的理解中,collect应该与map完全相同,但上面的代码仍然无法编译(我得到类型不匹配,因为foo无法解析)。在这种情况下,最好的方法是什么?
答案 0 :(得分:1)
collect
期望接收部分函数(不是函数或lambda),它将集合的元素作为输入:PartialFunction[B, Int]
。但是在这里你只想在另一个函数中调用你的PartialFunction[Int, Int]
,所以你甚至不能将PartialFunction
传递给collect
(你正在传递函数{{1} })。
没有(_.foo(i)): B => Int
的解决方案(但仍然collect
作为PartialFunction
的成员):
B
def getAll(i : Int): List[Int] = bs.flatMap(_.foo.lift(i))
将您的职能从lift
升级到PartialFunction[Int, Int]
。
如果你真的想要Int => Option[Int]
:
collect
import Function._
def getAll(i : Int): List[Int] = bs.collect(unlift(_.foo.lift(i)))
将unlift
缩减为B => Option[Int]
最丑陋的版本是PartialFunction[B, Int]
更好的解决方案是将您的部分功能移到collect{ case x if x.foo.isDefinedAt(i) => x.foo(i) }
之外:
B