Scala List.filter中的下划线
这不起作用的原因:Scala List.filter中的下划线,scala,Scala,这不起作用的原因: List(true,false).filter(_).size 错误显示: <console>:8: error: missing parameter type for expanded function ((x$1) => List(true, false).filter(x$1).size) List(true,false).filter(_).size ^ 我使用的是Scala 2.
List(true,false).filter(_).size
错误显示:
<console>:8: error: missing parameter type for expanded function
((x$1) => List(true, false).filter(x$1).size)
List(true,false).filter(_).size
^
我使用的是Scala 2.9.0.1。第一个错误是因为Scala不知道如何使用它。所以试试这个
List(true,false).filter(_:Boolean).size
之后,您将获得更多信息:
<console>:8: error: type mismatch;
found : Boolean
required: (Boolean) => Boolean
List(true,false).filter(_:Boolean).size
在Scala中处理
有点棘手,顺便说一句,我认为错误处理应该改进一点。回到主题,看一看这个例子:
def twice(i: Int) = i * 2
def gt2(j: Int) = j > 2
List(1,2,3) filter gt2
这可以很好地编译并按预期工作。但是,尝试组合函数时会出现神秘错误:
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(_))
^
发生了什么事?基本上,当Scala编译器看到下划线时,它会将其绑定到最直接的上下文中,在本例中是两次(41;
。这意味着我们现在使用函数作为参数调用gt2()
。编译器知道的是,这个函数接受一个参数并返回相同的类型。可以说,它应该计算出这个参数的类型,返回类型是基于tweeps()
签名的Int
,但是它暂时使用x$1
占位符,直到他稍后计算出来
不幸的是,它无法做到这一点,因为当我们提供函数时,gt2()
需要一个Int
(至少编译器是这么认为的)
那么,为什么:
List(1,2,3) filter {k => gt2(twice(k))}
工作?编译器事先不知道k
的类型。然而,它知道gt2
返回Boolean
,并期望Int
。它还知道tweeps()
需要Int
并返回一个。这样它就推断出k
的类型。另一方面,编译器从一开始就知道filter
需要Int=>Boolean
这是说回到你的情况。单独的下划线(<代码>(<)>代码>)不考虑“上下文”,因此编译器搜索另一个最直接的封闭上下文。_
将被视为一个函数本身,以及\u==true
。但不仅仅是下划线
那么,在这种情况下,最接近的直接上下文是什么(我相信它有一个科学名称…)?那么整个表达呢,
(x$1) => List(true, false).filter(x$1).size
编译器认为您正在尝试创建一个函数,该函数接受未知类型的参数并返回表达式类型的某些内容:List(true,false).filter(x$1).size
。同样可以论证的是,它应该能够计算出filter
接受Boolean=>Boolean
并返回Int
(.size
),但显然它没有
那你能做什么呢?您必须给编译器一个提示,即下划线应该在较小的上下文中解释。你可以说:
List(true,false) filter (_ == true)
List(true,false) filter (i => i)
List(true,false) filter identity
我看到错误消息有了很大的改进!让我们看看您编写的错误消息以及您的工作版本:
((x$1) => List(true, false).filter(x$1).size)
List(true,false).filter(a => a).size
或者,调整空格、括号和变量名:
a => List(true, false).filter(a ).size
List(true, false).filter(a => a).size
现在看起来一样吗
简单地说,当您传递下划线代替参数时,您正在执行以下操作。您可能更熟悉在匿名函数中用作参数占位符的下划线,这是它出现在表达式中时发生的情况,如\uu1
。这两种用法是不同的,即使它们都导致匿名函数。很好的解释。我可能不得不创建一些假帐户,以便对其进行多次投票。考虑到这种行为的许多问题,我认为编译器实际上最好不知道函数(Boolean=>Boolean)=>Int
是否合适,但编译失败。另请参阅:
((x$1) => List(true, false).filter(x$1).size)
List(true,false).filter(a => a).size
a => List(true, false).filter(a ).size
List(true, false).filter(a => a).size