如果方法是中缀和右关联,为什么Scala会为name-by-name参数计算参数?

Hol*_*ine 11 scala infix-notation lazy-evaluation callbyname

由于我理解call-by-name了方法的参数,因此在将参数表达式传递给方法时,不会计算相应的参数表达式,但只有在方法体中使用参数的值时(以及如果).

但是,在下面的例子中,这只在前两个方法调用中才有效,但在第三个方法调用中不是这样,尽管它应该只是第二种情况的语法变体!

为什么在第三个方法调用中计算参数表达式?

(我使用Scala 2.11.7测试了此代码)

class Node(x: => Int)

class Foo {
  def :: (x: =>Int) = new Node(x)  // a right-associative method
  def !! (x: =>Int) = new Node(x)  // a left-associative method
}

// Infix method call will not evaluate a call-by-name parameter:
val node = (new Foo) !! {println(1); 1}
println("Nothing evaluated up to here")

// Right-associative method call will not evaluate a call-by-name parameter:
val node1 = (new Foo).::({println(1); 1})
println("Nothing evaluated up to here")

// Infix and right-associative method call will evaluate a call-by-name parameter - why??
val node2 = {println(1); 1} ::(new Foo)  // prints 1
println("1 has been evaluated now - why??")
Run Code Online (Sandbox Code Playgroud)

Mic*_*jac 10

这是一个错误.那是一个旧的.

SI-1980和PR #2852.

链接的pull请求在使用-Xlint标志时添加了编译器警告:

<console>:13: warning: by-name parameters will be evaluated eagerly when called as a right-associative infix operator. For more details, see SI-1980.
         def :: (x: =>Int) = new Node(x)  // a right-associative method
             ^
Run Code Online (Sandbox Code Playgroud)


Jör*_*tag 3

只要提及名称参数,就会对它们进行求值。规范说右关联运算符方法调用的计算方式如下:

\n\n
a op_: b\n
Run Code Online (Sandbox Code Playgroud)\n\n

脱糖至:

\n\n
{ val someFreshName = a; b.op_:(someFreshName) }\n//                   \xe2\x86\x91\xe2\x86\x91\xe2\x86\x91\n// Eval happens here \xe2\x86\x91\xe2\x86\x91\xe2\x86\x91\n
Run Code Online (Sandbox Code Playgroud)\n