scala:匿名部分函数奇怪的语法

时间:2017-08-12 19:11:00

标签: scala

我遇到了类似于此的代码,它甚至编译时感到惊讶:

scala> val halfSize: PartialFunction[String, Int] = _.length match {
    case even if even % 2 == 0 => even / 2 
}
halfSize: PartialFunction[String,Int] = <function1>

scala> List("x", "xx").collect(halfSize)
res1: List[Int] = List(1)

据我所知,定义PartialFunction的有效语法是一个案例函数:

val halfSize: PartialFunction[String, Int] = { 
     case s if s.length % 2 == 0 => s.length / 2 
}

第一个代码似乎更加优化,因为它只调用length一次。但即使在SLS中,我也无法找到语法的解释。这是scalac的无证特征吗?

2 个答案:

答案 0 :(得分:0)

val halfSize: PartialFunction[String, Int] = _.length match {
    case even if even % 2 == 0 => even / 2 
}

上述函数中的下划线(_)只是一个简短的符号,表示函数的单个参数。因此,上面的代码片段只是

的简短形式
val halfSize: PartialFunction[String, Int] = { (x: String) => x.length match {
    case even if even % 2 == 0 => even / 2 
 }
}

答案 1 :(得分:0)

规则在https://www.scala-lang.org/files/archive/spec/2.12/06-expressions.html#anonymous-functions中给出:

  

匿名函数的最终运行时值由期望的类型确定:

     
      
  • ...

  •   
  • PartialFunction[T, U],如果函数文字的形状为x => x match { … }

  •   

在这种情况下,文字确实具有这样的形状,正如流氓的答案所解释的那样,因此PartialFunction被允许作为期望的类型。

(编辑:实际上,它没有,因为它匹配x.length而不是x。这看起来像一个小错误,但应该通过更改规范来修复。)

  

PartialFunction的值接收一个额外的isDefinedAt成员,该成员派生自函数文字中的模式匹配,每个case的正文被替换为true,并且添加了默认值(如果没有给出) )评估为假。

所以在这种情况下,最终会以

结束
def isDefinedAt(x: String) = x.length match {
  case even if even % 2 == 0 => true
  case _ => false
}