为什么和何时需要在方法名称后面加上_?

12

我对于何时需要在方法后面加一个_来将其用作函数还有些摸不着头脑。例如,为什么在以下代码中FooNil::会有所不同呢?

def square(n: Int) = n * n  
object Foo { def ::(f: Int => Int) = f(42) }

// ...

scala> Foo.::(square)
res2: Int = 1764

scala> Nil.::(square) 
<console>:6: error: missing arguments for method square in object $iw;
follow this method with `_' if you want to treat it as a partially applied function
   Nil.::(square)
          ^
scala> Nil.::(square _) 
res3: List[(Int) => Int] = List(<function1>)
1个回答

15

当您在部分应用函数表达式中省略所有参数时,需要在其后跟_,除非编译器在使用它的地方要求函数类型。

当您对Foo调用::方法时,编译器期望参数为Int => Int的类型。因此,在该位置安全地忽略square后面的下划线。

然而,在Nil上的::方法可以接受任何类型的参数。因此,除非您通过添加_来使其变得绝对明确,否则它会抱怨你意味着部分应用该函数。

所以这些就是规则......我无法真正启示您为什么这些是规则;也许对编译器、类型系统和语言设计有更好了解的其他人能够告诉您原因。但是,我假设如果没有这些规则,在许多地方都会存在意外歧义的危险。


2
谢谢。我刚刚发现了Scala语言规范的一部分,其中在Scala 2.0的更改说明中给出了一些理由:“已经收紧了将方法隐式转换为函数(§6.25)的规则。以前,作为值使用的参数化方法总是会被隐式转换为函数。当忘记方法参数时,这可能导致意外结果。例如,考虑下面的语句:show(x.toString)…” - Matt R

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接