2010-01-14 18 views
12

Tôi hơi run về các quy tắc khi bạn cần _ sau khi sử dụng phương thức này làm chức năng. Ví dụ: tại sao có sự khác biệt giữa Foo 's và Nil' s :: trong những điều sau đây?Tại sao và khi nào tôi cần phải làm theo tên phương thức với _?

def square(n: Int) = n * n 
object Foo { def ::(f: Int => Int) = f(42) } 

// ... 

scala> Foo.::(square) 
res2: Int = 1764 

scala> Nil.::(square) 
<console>:6: error: missing arguments for method square in object $iw; 
follow this method with `_' if you want to treat it as a partially applied function 
    Nil.::(square) 
     ^
scala> Nil.::(square _) 
res3: List[(Int) => Int] = List(<function1>) 

Trả lời

15

Khi bạn bỏ qua tất cả các tham số trong một biểu hiện chức năng áp dụng một phần, sau đó bạn cần phải làm theo nó với _trừ trình biên dịch đòi hỏi một loại chức năng tại địa điểm nơi bạn sử dụng nó.

Khi bạn gọi phương thức :: trên Foo, trình biên dịch mong đợi một loại Int => Int cho tham số. Vì vậy, bạn có thể bỏ qua một cách an toàn dấu gạch dưới sau square ở vị trí đó.

Tuy nhiên, phương pháp :: trên Nil có thể tham số bất kỳ loại nào. Vì vậy, thay vì giả sử rằng bạn có nghĩa là để áp dụng một phần chức năng, nó than phiền trừ khi bạn làm cho nó hoàn toàn rõ ràng bằng cách thêm _.

Vì vậy, đó là những quy tắc ... Tôi thực sự không thể khai sáng cho bạn về số lý do tại sao đó là các quy tắc; có lẽ ai đó có kiến ​​thức tốt hơn về trình biên dịch, hệ thống kiểu và thiết kế ngôn ngữ sẽ có thể cho bạn biết lý do. Nhưng tôi cho rằng nếu không có những quy tắc này, sẽ có nguy cơ tình cờ mơ hồ ở nhiều nơi.

+2

Cảm ơn. Chỉ tìm thấy một phần của đặc tả ngôn ngữ Scala cho một số lý do cho "lý do", trong ghi chú thay đổi cho Scala 2.0: "Các quy tắc cho chuyển đổi ngầm của các phương thức thành các hàm (§6.25) đã được thắt chặt. như một giá trị luôn được chuyển đổi hoàn toàn thành một hàm, điều này có thể dẫn đến các kết quả không mong đợi khi các đối số phương thức bị bỏ qua. –

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