[英]How to check if function is partial in Scala?
我有一个接收 function 的方法,但是 function 可能是部分的,在这种情况下我不希望它因 MatchError 而失败。
def doSomething[X,Y](opt:Option[X])(f:X=>Y)={
f match {
case p:PartialFunction[X,Y]=> opt.flatMap(p.lift) //This doesn't seem to work
case _ => opt.map(f)
}
}
这样我就可以使用这样的方法
doSomething(x){
case t if predicate(t) => otherMethod(t)
}
所以如果我没有谓词,我可以像这样使用它doSomething(x)(otherMethod)
而不是
doSoemthing(x){
case t=> otherMethod(t)
}
注意:寻找不需要捕获MatchError
异常的解决方案
这不是答案,因为我认为 Scala 不可能实现您想要的。
原始方法很好并且可以按预期工作,尽管它可能更简单一些:
def doSomething[X, Y](opt: Option[X])(f: X => Y): Option[Y] = {
f match {
case p: PartialFunction[X, Y] => opt.collect(p)
case _ => opt.map(f)
}
}
问题在这里:
doSomething(x){
case t if predicate(t) => otherMethod(t)
}
Scala 正在从该match
表达式创建Function
而不是PartialFunction
,因此测试失败。 如果您传递了一个真正的PartialFunction
,则该方法可以正常工作。
val p: PartialFunction[Int, Int] = {
case i: Int if i > 0 => i
}
doSomething(Some(0))(p) // Returns None
我认为没有任何方法可以做你想做的事,主要是因为doSomething
有多个参数列表,这会混淆第二个参数列表的类型推导。
我的建议只是使用
x.map(f)
或者
x.collect{
case ...
}
在调用代码中适当。
从 SLS 8.5 的 2.9 起,部分 function 的语法已更改,因此即使您这样做{ case x => y}
,也不意味着它是部分 function。 它的类型将与您定义的完全相同。
在您的情况下,您将其定义为X=>Y
(如在您的 function 参数中),所以它只是一个X=>Y
(它被编译成常规的 function,不匹配的情况会抛出 MatchError),甚至你做isInstanceOf[PartialFunciton[_,_]]
,它不会匹配。
为了使您的场景工作,您可以简单地将传递的 function 转换为 PartialFunction,例如:
doSomething(Some(1))({case 2 => 0}: PartialFunction[Int,Int]) //This returns None without MatchError
尽管
doSomething(Some(1)){case 2 => 0} //This gives MatchError and it is not recognized as PartialFunction inside the body
这可能不像您想象的那么方便,但它是使它工作的唯一方法。 (或者您为任何一种情况定义 2 个单独的函数,例如标准库中的collect
和map
)
我不确定你作为部分 Function 传递的是什么,但绝对你应该用这样的特定签名来定义它:
val positive: PartialFunction[Int, Option[Int]] = {
case x if x >= 0 => Some(x)
case _ => None
positive
function 仅针对正数定义。 如果是负数,则 function 返回 None 并且您不会在运行时收到 scala.MatchError 。
这个特定的 function 使您能够访问isDefinedAt
方法,该方法正在动态测试值是否在 function 的域中。
postive(5).isDefinedAt // 真
poistive.isInstanceOf[PartialFunction[Int, Option[Int]]] // 真
我在这里演示了为什么在检查p.isInstanceOf
时总是会出错
def doSomething[X,Y](opt:Option[X])(f:X=>Y)={
f match {
case p if p.isInstanceOf[PartialFunction[X,Y]] =>
println("I'm a pf")
println(s"Is it PartialFunction: ${p.isInstanceOf[PartialFunction[X,Y]]}")
opt.map(p)
case _ =>
println("I'm not a pf")
opt.map(f)
}
}
doSomething[Int, Option[Int]](Some(5))(positive) // partial function case
doSomething[Int, String](Some(5)) { // tricky case
case s => s.toString
}
你可以在这里玩它:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.