2015-11-11 17 views
11

Khi tôi hiểu các tham số call-by-name của một phương thức, biểu thức đối số tương ứng sẽ không được đánh giá khi chuyển nó sang phương thức, nhưng chỉ khi (và nếu) giá trị của tham số được sử dụng trong thân phương thức. Tuy nhiên, trong ví dụ sau đây, điều này chỉ đúng trong hai cuộc gọi phương thức đầu tiên, nhưng không phải trong ví dụ thứ hai, mặc dù nó chỉ là một biến thể đơn thuần của trường hợp thứ hai !?Tại sao Scala đánh giá đối số cho tham số gọi theo tên nếu phương thức là infix và right-associative?

Tại sao biểu thức đối số được đánh giá trong cuộc gọi phương thức thứ ba?

(Tôi thử mã này sử dụng 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??") 

Trả lời

3

By-tên đối số được đánh giá bất cứ khi nào họ được đề cập. The spec says mà phải kết hợp lời gọi phương thức điều hành được đánh giá như thế này:

a op_: b 

desugars tới:

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

Đó là một lỗi. Một cái cũ, lúc đó.

Xem SI-1980 và PR #2852.

Yêu cầu kéo liên kết thêm một cảnh báo trình biên dịch khi sử dụng -Xlint cờ:

<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

Cảm ơn, m-z, cho câu trả lời nhanh và chính xác. Rõ ràng, nó không làm cho tôi hạnh phúc, nhưng đó không phải là lỗi của bạn ;-) –

+0

Tôi sẽ không gọi đó là một lỗi. Đó là những gì spec nói, và những gì spec đã luôn luôn nói cho đến khi các cuộc gọi nhà điều hành kết hợp quyền liên kết đã được trong ngôn ngữ, theo như tôi biết. Thông thường mọi người phàn nàn khi trình biên dịch không tuân theo spec, bây giờ nó có, và họ vẫn không hài lòng :-D (Tôi hiểu và hết lòng đồng ý rằng hành vi được chỉ định làm cho các đối số tên hoàn toàn vô dụng cho các cuộc gọi điều khiển kết hợp phải , nhưng một lỗi là khi spec không đồng ý với việc thực hiện, không phải khi bạn và tôi không đồng ý với thông số kỹ thuật!) –

+0

@ JörgWMittag Đủ công bằng. Các cuộc thảo luận trong SI-1980 chỉ ra rằng 6.12.3 có phần mâu thuẫn với 4.6.2 trong spec. Nếu nó không được coi là một lỗi, sau đó nó vượt ra ngoài tôi tại sao vấn đề vẫn còn mở và dán nhãn như vậy. –

Các vấn đề liên quan