2015-11-11 18 views
11

Come ho capito i parametri call-by-name di un metodo, l'espressione dell'argomento corrispondente non verrà valutata quando lo si passa al metodo, ma solo quando (e se) il valore del parametro viene utilizzato nel corpo del metodo.Perché Scala valuta l'argomento per un parametro call-by-name se il metodo è infisso e right-associative?

Nel seguente esempio, tuttavia, questo è vero solo nelle prime due chiamate di metodo, ma non nel terzo, sebbene dovrebbe essere una variazione puramente sintattica del secondo caso !?

Perché l'espressione dell'argomento viene valutata nella terza chiamata al metodo?

(Ho provato questo codice usando 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??") 

risposta

3

By-nome argomenti vengono valutati ogni volta che vengono menzionati. The spec says che chiamate di metodo operatore destro associativi vengono valutati in questo modo:

a op_: b 

desugars a:

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

E 'un bug. Uno vecchio, a quello.

Vedere SI-1980 e PR #2852.

La richiesta di pull collegato aggiunto un avviso del compilatore quando si utilizza il 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 
      ^
+0

Grazie, m-z, per la risposta rapida e corretta. Ovviamente, non mi rende felice, ma non è colpa tua ;-) –

+0

Non direi che un bug. È quello che dicono le specifiche, e ciò che le specifiche hanno sempre detto fino a quando le chiamate degli operatori in-right associativi sono state nella lingua, per quanto ne so. Di solito le persone si lamentano quando il compilatore non segue le specifiche, ora lo fa, e non sono ancora felici MrGreen (Capisco e condivido con tutto il cuore che il comportamento specificato rende totalmente inutili le argomentazioni per nome per le chiamate operatore di destra associative , ma un bug è quando la specifica non è d'accordo con l'implementazione, non quando tu ed io non siamo d'accordo con le specifiche!) –

+0

@ JörgWMittag Abbastanza giusto. La discussione su SI-1980 sottolinea che il 6.12.3 è in qualche modo contraddetto dal 4.6.2 nelle specifiche. Se non è considerato un bug, allora è oltre me il motivo per cui il problema è ancora aperto ed etichettato come tale. –