2013-01-24 33 views
6

Tôi bắt đầu học Scala và tôi đã xem một đoạn trích từ sách giáo khoa Lập trình trong Scala mà tôi không hiểu lắm. Đã hy vọng một số người có thể giúp tôi?Hiểu Scala: chuyển các hàm làm đối số

Đây là từ Liệt kê 9.1 từ Lập trình trong Scala, 2nd Edition.

object FileMatcher { 
    private def filesHere = (new java.io.File(".")).listFiles 
} 

private def filesMatching(matcher: String => Boolean) = 
    for (file <- filesHere; if matcher(file.getName)) yield file 

def filesEnding(query: String) = 
    filesMatching(_.endsWith(query)) // ??? 

def filesContaining(query: String) = 
    filesMatching(_.contains(query)) // ??? 

def filesRegex(query: String) = 
    filesMatching(_.matches(query)) // ??? 

Tôi hơi bối rối với các dòng có // ???. Việc sử dụng các _ bằng cách nào đó tạo ra một chức năng nặc danh được chuyển đến filesMatching? Hoặc không _ không có gì để làm với điều này, và thay vào đó trình biên dịch thấy rằng filesMatching đòi hỏi một chức năng và do đó không thực hiện _.endsWith(query) như một biểu thức mà thay vào đó làm cho biểu thức một chức năng?

+1

Không có dòng nào có '// ???' ở trên. Có lẽ bạn quên thêm những? –

+0

Xin lỗi về điều đó, đã thêm '// ???' ngay bây giờ. – C0deAttack

+0

có thể trùng lặp của [Scala \ _ Placeholders (Mã này hoạt động như thế nào?)] (Http://stackoverflow.com/questions/6880407/scala-placeholders-how-does-this-code-function) –

Trả lời

14

định nghĩa mở rộng

Hàm ẩn danh được xác định, dưới hình thức tiết hơn và đầy đủ của họ, như

(a: A, b: B, ...) => function body //using a, b, ... 

Ví dụ:

(a: String, b: String) => a ++ b // concatenates 2 Strings 

loại suy ra

nếu bối cảnh cung cấp các thông tin cần thiết (như khi một hàm bậc cao hy vọng một chữ ký cụ thể cho các đối số chức năng của nó), bạn có thể bỏ qua các loại các thông số, như

(a, b, ...) => function body //using a, b, ... 

Ví dụ:

val l = List(1, 2, 3) 

//you can omit the type because filter on List[Int] expects a (Int => Boolean) 
l.filter(i => i < 3) 

cú pháp placeholder

Cuối cùng, bạn có thể sử dụng một hình thức ngắn hơn vẫn còn, nếu thông số của bạn đang sử dụng một lần mỗi và theo thứ tự mà bạn khai báo, bởi các cơ quan chức năng, như

_ ++ _ // which is equivalent to (a, b) => a ++ b 

Mỗi _ là một giữ chỗ cho các đối số của hàm

Ví dụ:

filesMatching 's đối số là một chức năng của loại String => Boolean vì vậy bạn có thể sử dụng

_.endsWith(query) // equivalent to (s: String) => s.endsWith(query) 
_.contains(query) // equivalent to (s: String) => s.contains(query) 
_.matches(query) // equivalent to (s: String) => s.matches(query) 
3

_ như được sử dụng ở đây là viết tắt của đối số hàm. Do đó filesMatching(_.endsWith(query)) tương đương với filesMatching(f => f.endsWith(query)). Vì filesMatching có tham số là hàm của String => Boolean, trình biên dịch có thể phỏng đoán rằng f được mong đợi là String tại đây. Vì vậy, bạn nói đúng rằng biểu thức này là một hàm ẩn danh.

0

loại này hoạt động được thực hiện tốt nhất bằng cách định nghĩa các loại chức năng. Tôi tìm thấy một cuộc biểu tình tuyệt vời here.Kết hợp với bài đăng này, bản trình diễn phải làm rõ các phương pháp hay nhất để chuyển các chức năng như các đối số

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