为什么这不起作用:
List(true,false).filter(_).size
Run Code Online (Sandbox Code Playgroud)
错误说:
<console>:8: error: missing parameter type for expanded function
((x$1) => List(true, false).filter(x$1).size)
List(true,false).filter(_).size
^
Run Code Online (Sandbox Code Playgroud)
但以下作品(对我来说看起来一样):
List(true,false).filter(a => a).size
Run Code Online (Sandbox Code Playgroud)
我正在使用Scala 2.9.0.1.
Tom*_*icz 23
_在Scala中处理有点棘手,作为旁注,我认为错误处理应该有所改进.回到主题,看看这个例子:
def twice(i: Int) = i * 2
def gt2(j: Int) = j > 2
List(1,2,3) filter gt2
Run Code Online (Sandbox Code Playgroud)
这编译好并按预期工作.但是,尝试撰写函数会导致隐藏错误:
List(1,2,3) filter gt2(twice(_))
error: missing parameter type for expanded function ((x$1) => twice(x$1))
List(1,2,3) filter gt2(twice(_))
^
Run Code Online (Sandbox Code Playgroud)
发生了什么?基本上,当Scala编译器看到下划线时,它会将其绑定到最直接的上下文中,twice(_)在这种情况下.这意味着我们现在gt2()使用函数 twice作为参数进行调用.编译器知道的是该函数接受一个参数并返回相同的类型.可以说它应该弄清楚这个参数的类型,并且返回类型是Int基于twice()签名的,但是它x$1暂时使用占位符,直到他稍后想出来.
不幸的是,它无法做到这一点,因为我们gt2()期待一段Int时间我们提供一个函数(至少这是编译器认为的).
那么为什么:
List(1,2,3) filter {k => gt2(twice(k))}
Run Code Online (Sandbox Code Playgroud)
工作?编译器k事先不知道类型.然而,它知道gt2回报Boolean和预期的Int.它也知道twice()期望a Int并返回一个.这样它就可以推断出它的类型k.另一方面,编译器从一开始就知道filter期望Int => Boolean.
这是回到你的情况.单独的下划线((_))不考虑" 上下文 ",因此编译器会搜索另一个最直接的封闭上下文.在!_过去被认为与自身的功能,以及_ == true.但不仅仅是下划线.
那么在这种情况下,最接近的直接背景是什么(我确定有一个科学名称......)?好吧,整个表达方式:
(x$1) => List(true, false).filter(x$1).size
Run Code Online (Sandbox Code Playgroud)
编译器认为您正在尝试创建一个函数,该函数接受一些未知类型的参数并返回表达式的某些类型:List(true, false).filter(x$1).size.再次可以说它应该能够找出filtertake Boolean => Boolean和returns Int(.size),但显然它没有.
所以,你可以做什么?您必须为编译器提供一个提示,即应在较小的上下文中解释下划线.你可以说:
List(true,false) filter (_ == true)
List(true,false) filter (i => i)
List(true,false) filter identity
Run Code Online (Sandbox Code Playgroud)