Why does Scala evaluate the argument for a call-by-name parameter if the method is infix and right-associative?

我只是一个虾纸丫 提交于 2019-12-04 02:57:34

问题


As I understood call-by-name parameters of a method, the corresponding argument expression will not be evaluated when passing it to the method, but only when (and if) the value of the parameter is used in the method body.

In the following example, however, this is only true in the first two method calls, but not in the third one, although it should be a merely syntactical variation of the second case!?

Why is the argument expression evaluated in the third method call?

(I tested this code using 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??")

回答1:


By-name arguments are evaluated whenever they are mentioned. The spec says that right-associative operator method calls are evaluated like this:

a op_: b

desugars to:

{ val someFreshName = a; b.op_:(someFreshName) }
//                   ↑↑↑
// Eval happens here ↑↑↑



回答2:


It's a bug. An old one, at that.

See SI-1980 and PR #2852.

The linked pull request added a compiler warning when using the -Xlint flag:

<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
             ^


来源:https://stackoverflow.com/questions/33656557/why-does-scala-evaluate-the-argument-for-a-call-by-name-parameter-if-the-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!