带有 isDefinedA 的 Scala PartialFunction 并应用不起作用

问题描述

我是 Scala 新手,我正在尝试 PartialFunctions,这是测试功能的正确方法吗,因为一些教程遵循此方法可以工作,但对我不起作用?

代码

object MyScalaApp extends App {
def try29{
    val r = new PartialFunction[Int,Int]  
    { 
        def isDefinedAt(q: Int) = q < 0 // Applying isDefinedAt method  
        def apply(q: Int) = 12 * q // Applying apply method 
    }        
    val rr = new PartialFunction[Double,Double]  
    { 
        def isDefinedAt(q: Double) = {q < 0}
        def apply(q: Double) = 12 * q 
    }

    println(r(1))
    println(r(2))        
    println(rr(-1))
    println(rr(-2))
  }
  }
  try29
}

输出

12
24
-12.0
-24.0

为什么 apply 在不匹配第一个条件时会被调用
当我写 def isDefinedAt(q: Int) = q != 0 时,它给出 println(r(0)) 作为输出 0

解决方法

根据ScalaDocs page

调用者有责任在调用 isDefinedAt 之前调用 apply...

让我们在自动调用 r() 的上下文中尝试您的 isDefinedAt() 偏函数。

val r = new PartialFunction[Int,Int] {
  def isDefinedAt(q: Int) = q < 0
  def apply(q: Int) = 12 * q
}
List(4,-3,22,-9,0).collect(r)
//res0: List[Int] = List(-36,-108)

似乎按预期工作。

,

这不完全是你问的,但我认为值得一提的是 applyOrElse 的存在。如果以后您打算编写代码,例如:

if(r.isDefinedAt(1)) r(1) else 10

最好使用 applyOrElse,如文档中所述:

注意表达式 pf.applyOrElse(x,default) 等价于

if(pf isDefinedAt x) pf(x) else default(x)

除了 applyOrElse 方法可以更有效地实现。对于所有部分函数文字,编译器生成一个 applyOrElse 实现,以避免对模式匹配器和保护器进行双重评估。这使得 applyOrElse 成为高效实施许多操作和场景的基础。