2015-11-11 11 views
11

Wie ich call-by-name Parameter einer Methode verstanden habe, wird der entsprechende Argumentausdruck nicht ausgewertet, wenn er an die Methode übergeben wird, sondern nur wenn (und falls) der Wert des Parameters im Methodenrumpf verwendet wird.Warum wertet Scala das Argument für einen Call-by-Name-Parameter aus, wenn die Methode infix und rechtsassoziativ ist?

Im folgenden Beispiel gilt dies jedoch nur für die ersten beiden Methodenaufrufe, nicht aber für den dritten, obwohl es sich um eine einfache syntaktische Variante des zweiten Falles handeln sollte !?

Warum wird der Argumentausdruck im dritten Methodenaufruf ausgewertet?

(I getestet mit diesem Code 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??") 

Antwort

3

By-Name Argumente ausgewertet werden, wann immer sie genannt werden. The spec says dass rechts assoziativer Operator Methodenaufrufe wie folgt bewertet werden:

a op_: b 

desugars zu:

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

Es ist ein Fehler. Ein alter, bei dem.

Siehe SI-1980 und PR #2852.

Die verknüpfte Pull-Anforderung hinzugefügt, um eine Warnung Compiler, wenn die -Xlint Flag verwendet:

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

Dank, m-z, für die schnelle und richtige Antwort. Offensichtlich macht es mich nicht glücklich, aber das ist nicht deine Schuld ;-) –

+0

Ich würde das nicht als Bug bezeichnen. Es ist, was die Spezifikation sagt, und was die Spezifikation immer gesagt hat, solange rechts-assoziative Infix-Operator-Aufrufe in der Sprache waren, soweit ich weiß. Gewöhnlich beschweren sich die Leute, wenn der Compiler der Spezifikation nicht folgt, jetzt tut es das und sie sind immer noch nicht glücklich :-D (Ich verstehe und stimme voll und ganz zu, dass das angegebene Verhalten die Namen-Argumente für rechts-assoziative Infix-Operator-Aufrufe völlig nutzlos macht , aber ein Fehler ist, wenn die Spezifikation nicht mit der Implementierung übereinstimmt, nicht wenn Sie und ich mit der Spezifikation nicht einverstanden sind!) –

+0

@ JörgWMittag Fair genug. Die Diskussion in SI-1980 weist darauf hin, dass 6.12.3 etwas von 4.6.2 in der Spezifikation widerlegt wird. Wenn es sich nicht um einen Fehler handelt, liegt es an mir, warum das Problem noch offen und als solches gekennzeichnet ist. –