在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)
因此,将表达式键入PartialFunction或Function影响表达式的编译方式.
也trait PartialFunction [-A, +B] extends (A) ? B所以部分功能PartialFunction[A,B]也是一个Function[A,B].
- 修订后 -
嗯,我不确定我看到了什么区别,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)
它看起来f和g表现完全相同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.