天哪,这是一个微妙的问题,但据我所知,它遵循Scala 规范 http://www.scala-lang.org/docu/files/ScalaReference.pdf完全地。我将引用 2.9 版规范中的内容。
对于您的第一个示例:正如您所说,您正在通过方法值的特殊情况(第 6.7 节)看到 eta 扩展:
The expression e _ is well-formed if e is of method type or if e is a call-by-name parameter. If e is a method with parameters, e _ represents e converted to a function type by eta expansion.
§6.26.5 中给出了 eta 扩展的算法,您可以按照该算法对表达式进行以下替换new Foo().x1 _
:
{
val x1 = new Foo();
(y1: Int) => x1.(y1);
}
这意味着当使用 eta 扩展时,所有子表达式都会在转换发生时进行计算(如果我正确理解了短语“最大子表达式”的含义),并且最终表达式是创建的的匿名函数。
在第二个示例中,这些额外的括号意味着编译器将查看第 6.23 节(特别是“匿名函数的占位符语法”)并直接创建匿名函数。
An expression (of syntactic category Expr) may contain embedded underscore symbols _ at places where identifiers are legal. Such an expression represents an anonymous function where subsequent occurrences of underscores denote successive parameters.
在这种情况下,按照该部分中的算法,您的表达式最终将是这样的:
(x1: Int) => new Foo().foo(x1)
差异是微妙的,正如 @Antoras 很好地解释的那样,只有在存在副作用代码时才真正显示出来。
请注意,针对涉及按名称调用代码块的情况正在修复错误(例如,请参阅这个问题 https://stackoverflow.com/q/4918362/991432, this bug https://issues.scala-lang.org/browse/SI-302 and this bug https://issues.scala-lang.org/browse/SI-5610).
后记:在这两种情况下,匿名函数(x1:Int) => toto
扩展到
new scala.Function1[Int, Int] {
def apply(x1: Int): Int = toto
}