本文介绍了List.filter 中的下划线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么这不起作用:

List(true,false).filter(_).size

错误说:

:8: 错误:缺少扩展函数的参数类型((x$1) => List(true, false).filter(x$1).size)列表(真,假).过滤器(_).大小^

但以下有效(对我来说看起来一样):

List(true,false).filter(a => a).size

我使用的是 Scala 2.9.0.1.

解决方案

_ 的处理在 Scala 中有点棘手,作为旁注,我认为应该稍微改进错误处理.回到主题,看看这个例子:

def 两次(i: Int) = i * 2def gt2(j: Int) = j >2列表(1,2,3)过滤器 gt2

这可以正常编译并按预期工作.然而,尝试组合函数会导致神秘错误:

List(1,2,3) filter gt2(twice(_))错误:缺少扩展函数的参数类型((x$1)=> 两次(x$1))列表(1,2,3)过滤器gt2(两次(_))^

发生了什么?基本上,当 Scala 编译器看到下划线时,它将它绑定到最直接的上下文中,在这种情况下是 twice(_).这意味着我们现在使用 function twice 作为参数调用 gt2().编译器知道的是这个函数接受一个参数并返回相同的类型.可以说它应该根据 twice() 签名确定这个参数的类型和返回类型是 Int,但是它暂时使用 x$1 占位符直到他后来弄清楚.

不幸的是它无法做到这一点,因为 gt2() 在我们提供一个函数时需要一个 Int(至少编译器是这么认为的).>

为什么会这样:

List(1,2,3) filter {k =>gt2(两次(k))}

工作?编译器事先不知道k 的类型.然而它知道gt2 返回Boolean 并期望一个Int.它还知道 twice() 需要一个 Int 并返回一个.这样它就可以推断出 k 的类型.另一方面,编译器从一开始就知道 filter 期望 Int =>布尔值.

回到你的情况.单独的下划线 ((_)) 不被视为context",因此编译器搜索另一个最直接的封闭上下文.!__ == true 一样被认为是一个函数.但不仅仅是下划线.

那么在这种情况下,最接近的直接上下文是什么(我确定它有一个科学名称......)?好吧,整个表达:

(x$1) =>列表(真,假).过滤器(x$1).大小

编译器认为您正在尝试创建一个函数,该函数接受一些未知类型的参数并返回表达式类型的某些内容:List(true, false).filter(x$1).size.再次可以说它应该能够弄清楚 filter 需要 Boolean =>Boolean 并返回 Int (.size),但显然没有.

那你能做什么?您必须向编译器提示下划线应在较小的上下文中解释.你可以说:

List(true,false) 过滤器 (_ == true)列表(真,假)过滤器(i => i)列表(真,假)过滤标识

Why this is not working:

List(true,false).filter(_).size

The error says:

<console>:8: error: missing parameter type for expanded function 
((x$1) => List(true, false).filter(x$1).size)
    List(true,false).filter(_).size
                            ^

but the following works (looks just the same for me):

List(true,false).filter(a => a).size

I'm using Scala 2.9.0.1.

解决方案

Handling of _ is a bit tricky in Scala and as a side note I think error handling should be improved a bit. Back to topic, have a look at this example:

def twice(i: Int) = i * 2
def gt2(j: Int) = j > 2

List(1,2,3) filter gt2

This compiles fine and works as expected. However trying to compose functions results with cryptic error:

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(_))
                                     ^ 

What happened? Basically when Scala compiler sees underscore it binds it into the most immediate context, which is twice(_) in this case. This means we are now calling gt2() with a function twice as an argument. What compiler knows is that this function takes an argument and returns the same type. Arguably it should figure out the type of this argument and return type is Int based on twice() signature, however it uses x$1 placeholder temporarily until he figures that out later.

Unfortunately it is unable to do that since gt2() expects an Int while we are providing a function (at least that is what the compiler thinks).

So why does:

List(1,2,3) filter {k => gt2(twice(k))}

work? The compiler does not know the type of k in advance. However it knows that gt2 returns Boolean and expected an Int. It also knows that twice() expects an Int and returns one as well. This way it infers the type of k. On the other hand the compiler knows from the beginning that filter expects Int => Boolean.


That being said back to your case. The underscore alone ((_)) is not consider a "context" so the compiler searches for another most immediate enclosing context. The !_ would have been considered a function on its own, as well as _ == true. But not the underscore alone.

So what is the closest immediate context (I'm sure there is a scientific name for that...) in this case? Well, the whole expression:

(x$1) => List(true, false).filter(x$1).size

The compiler thinks you are trying to create a function that takes some parameter of unknown type and returns something of the type of an expression: List(true, false).filter(x$1).size. Again arguably it should be able to figure out that filter takes Boolean => Boolean and returns Int (.size), but apparently it doesn't.


So what can you do? You have to give the compiler a hint that the underscore should be interpreted in smaller context. You can say:

List(true,false) filter (_ == true)
List(true,false) filter (i => i)
List(true,false) filter identity

这篇关于List.filter 中的下划线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-31 22:04