简体   繁体   English

如果方法是中缀和右关联的,为什么 Scala 会评估按名称调用参数的参数?

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

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.正如我所理解的方法call-by-name参数,在将其传递给方法时不会评估相应的参数表达式,而只会在(以及如果)方法体中使用参数的值时进行计算。

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) (我使用 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??")

Edit of 2020: Note that Scala 2.13 no longer shows this irritating behavior: val node2 = ... no longer prints anything. 2020 年编辑:请注意,Scala 2.13 不再显示这种令人讨厌的行为: val node2 = ...不再打印任何内容。

It's a bug.这是一个错误。 An old one, at that.一个旧的,在那个。

See SI-1980 and PR #2852 .参见SI-1980和 PR #2852

The linked pull request added a compiler warning when using the -Xlint flag:链接的拉取请求在使用-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
             ^

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM