如何在Scala中省略匹配词?

Ami*_*far 12 scala

在Scala中,你可以做到

list.filter { item =>
    item match {
      case Some(foo) => foo.bar > 0
    }
}
Run Code Online (Sandbox Code Playgroud)

但是你也可以通过省略来更快地做到match:

list.filter {
  case Some(foo) => foo.bar > 0
}
Run Code Online (Sandbox Code Playgroud)

Scala如何支持这一点?这是2.9的新功能吗?我一直在寻找它,我可以弄清楚是什么让这成为可能.它只是Scala编译器的一部分吗?

Jea*_*let 18

编辑:这个答案的部分内容是错误的; 请参考huynhjl的回答.


如果省略match,则表示编译器正在定义部分函数.部分函数是未针对每个输入值定义的函数.例如,您的过滤器函数仅针对类型的值Some[A](针对您的自定义类型A)定义.

PartialFunctionMatchError当你试图将它们应用于未定义的地方时,抛出一个.因此,当你传递一个定义PartialFunction常规的地方时,你应该确保Function你的部分函数永远不会被一个无法使用的参数调用.这样的机制非常有用,例如解压集合中的元组:

val tupleSeq: Seq[(Int, Int)] = // ...
val sums = tupleSeq.map { case (i1, i2) => i1 + i2 }
Run Code Online (Sandbox Code Playgroud)

要求部分功能的API,如collect对集合的类似过滤器的操作,通常isDefinedAt在应用部分函数之前调用.在那里,安全(并且经常需要)具有未针对每个输入值定义的部分功能.

所以你看到虽然语法接近于a的语法match,但实际上我们正在处理它们.


huy*_*hjl 14

语言规范还解决了8.5节.相关部分:

匿名函数可以由一系列案例定义

{ case p1 => b1 ... case pn => bn }
Run Code Online (Sandbox Code Playgroud)

如果期望的类型是scala.Functionk[S1, ..., Sk, R],则表达式被认为等同于匿名函数:

(x1 : S1, ..., xk : Sk) => (x1, ..., xk) match {
  case p1 => b1 ... case pn => bn
}
Run Code Online (Sandbox Code Playgroud)

如果期望的类型是scala.PartialFunction[S, R],则表达式被认为等同于以下实例创建表达式:

new scala.PartialFunction[S, T ] {
  def apply(x: S): T = x match {
    case p1 => b1 ... case pn => bn
  }
  def isDefinedAt(x: S): Boolean = {
    case p1 => true ... case pn => true
    case _ => false
  }
}  
Run Code Online (Sandbox Code Playgroud)

因此,将表达式键入PartialFunctionFunction影响表达式的编译方式.

trait PartialFunction [-A, +B] extends (A) ? B所以部分功能PartialFunction[A,B]也是一个Function[A,B].


Kip*_*ros 6

- 修订后 -

嗯,我不确定我看到了什么区别,Scala 2.9.1.RC3,

val f: PartialFunction[Int, Int] = { case 2 => 3 }
f.isDefinedAt(1) // evaluates to false
f.isDefinedAt(2) // evaluates to true
f(1) // match error

val g: PartialFunction[Int, Int] = x => x match { case 2 => 3 }
g.isDefinedAt(1) // evaluates to false
g.isDefinedAt(2) // evaluates to true
g(1) // match error
Run Code Online (Sandbox Code Playgroud)

它看起来fg表现完全相同PartialFunctions.

这是另一个证明等价的例子:

Seq(1, "a").collect(x => x match { case s: String => s }) // evaluates to Seq(a)
Run Code Online (Sandbox Code Playgroud)

更有趣的是:

// this compiles
val g: PartialFunction[Int, Int] = (x: Int) => {x match { case 2 => 3 }}

// this fails; found Function[Int, Int], required PartialFunction[Int, Int]
val g: PartialFunction[Int, Int] = (x: Int) => {(); x match { case 2 => 3 }}
Run Code Online (Sandbox Code Playgroud)

所以这是在编译器级别的一些特殊外壳之间进行转换x => x match {...} ,只是{...}.

更新.阅读语言规范后,这对我来说似乎是个错误.我在错误跟踪器中提交了SI-4940.