2010-09-20 29 views
23

Tôi đã thấy rằng Scala luôn luôn có một "giải thích tự nhiên" cho bất cứ điều gì. Luôn luôn một cái gì đó như "ohh, nhưng đó chỉ là một chức năng được gọi là trên này và đối tượng với điều này và tham số đó". Trong một nghĩa nào đó, không có gì thực sự là biên dịch-ma thuật như chúng ta biết từ các ngôn ngữ khác.Scala "<-" để hiểu được

Câu hỏi của tôi là trên <- điều hành được sử dụng trong đoạn mã sau:

for(i <- 0 to 10) println(i) 

Trong ví dụ này tôi có thể nhìn thấy nó được viết lại để cái gì đó như:

0.to(10).foreach((i:Int)=>println(i)) 

nhưng điều này không giải thích cách các số i được đưa vào anon chức năng ymous bên trong chức năng foreach. Tại thời điểm bạn viết i nó không phải là một đối tượng và chưa phải là biến được khai báo. Vì vậy, nó là gì, và làm thế nào nó được chuyển sang bên trong của foreach?

tôi đoán là cuối cùng tôi phát hiện ra một cái gì đó mà là trong thực tế biên dịch ma thuật

Cảm ơn thời gian của bạn.

Để làm rõ, câu hỏi của tôi là: cách < - toán tử hoạt động trong dòng mã thứ nhất vì tôi không phải là đối tượng mà trên đó nó có thể được gọi là hàm.

Trả lời

18

<- là một ngôn ngữ biểu tượng từ khóa được xác định, như là => nhưng có độ tương phản riêng với -> (biểu tượng được xác định). Bởi vì nó là một phần của ngữ pháp Scala cơ bản, nó có thể được sử dụng để tạo các ràng buộc (cho ví dụ của bạn) là một cái gì đó mà không thể được thực hiện bởi các cấu trúc do người dùng định nghĩa.

+0

Điều này có vẻ là câu trả lời. Tôi sẽ đề nghị bạn ghi lại điều này nếu có thể, bây giờ nó không còn là màu xanh nữa. – Felix

+4

@Felix: Tài liệu được mô tả trong đặc điểm kỹ thuật. Và khá nhiều cuốn sách Scala có sẵn trên thị trường bao gồm nó. – missingfaktor

+0

oh yeah, tôi chưa nhận được cuốn sách nào. chờ đợi cho cuốn sách 2.8 dứt khoát – Felix

6

Trong trường hợp này, nó thực sự là một chút ma thuật trình biên dịch. Dịch từ hiểu cho đến bộ lọc/bản đồ/dạng phẳng là một bit đặc biệt của desugaring, giống như chuyển đổi các hình thức đặc biệt của bản cập nhật và áp dụng các phương pháp.

57

Để tăng thêm câu trả lời của Dave, đây là một sơ đồ dịch cho 'cho-comprehensions' từ đặc tả ngôn ngữ Scala:

Một sự hiểu biết for (enums) yield e đánh giá biểu hiện e cho mỗi ràng buộc tạo ra bởi các enums điều tra viên. Một chuỗi điều tra luôn luôn bắt đầu với một máy phát điện; điều này có thể được theo sau bởi các máy phát điện bổ sung, định nghĩa giá trị hoặc bảo vệ.

Máy phát điện p <- e tạo liên kết từ biểu thức e được đối sánh theo cách nào đó với mẫu p. Định nghĩa giá trị val p = e liên kết tên giá trị p (hoặc một số tên trong mẫu p) với kết quả của việc đánh giá biểu thức e. Một bảo vệ if e chứa một biểu thức boolean hạn chế các ràng buộc được liệt kê.

Ý nghĩa chính xác của máy phát điện và bảo vệ được xác định bởi dịch để invocations của bốn phương pháp: map, filter, flatMap, và foreach. Các phương thức này có thể được thực hiện theo nhiều cách khác nhau cho các loại sóng mang khác nhau.

Lược đồ dịch như sau. Trong bước đầu tiên, mỗi máy phát điện p <- e, trong đó p không phải là không thể chối cãi (§8.1) cho các loại e được thay thế bằng

p <- e.filter { case p => true; case _ => false } 

Sau đó, các quy tắc sau được áp dụng lặp đi lặp lại cho đến khi tất cả comprehensions đã loại bỏ.

  • A for-comprehension for (p <- e) yield e0 được dịch sang e.map { case p => e0 }.

  • Đọc hiểu for (p <- e) e0 được dịch sang e.foreach { case p => e0 }.

  • A for-comprehension for (p <- e; p0 <- e0 . . .) yield e00, ở đâu. . . là một chuỗi máy phát hoặc bộ phận bảo vệ (có thể trống), được dịch tới:
    e.flatMap { case p => for (p0 <- e0 . . .) yield e00 }.

  • A for-comprehension for (p <- e; p0 <- e0 . . .) e00 ở đâu. . . là một chuỗi máy phát hoặc bộ phận bảo vệ (có thể trống), được dịch sang:
    e.foreach { case p => for (p0 <- e0 . . .) e00 }.

  • Một máy phát điện p <- e Tiếp theo một người bảo vệ if g được phiên dịch sang một máy phát điện duy nhất:
    p <- e.filter((x1, . . . , xn) => g)
    nơi x1,. . . , xn là các biến miễn phí của p.

  • Một máy phát điện p <- e theo sau là một định nghĩa giá trị val p0 = e0 được dịch để máy phát điện sau đây của cặp giá trị, nơi xx0 là những cái tên mới:

    val (p, p0) <- 
        for([email protected] <- e) yield { val [email protected] = e0; (x, x0) } 
    
+1

Được rồi, tôi không hiểu mọi thứ sau lần đọc đầu tiên, nhưng thật thú vị :-) Bạn đã nhận được thông tin này ở đâu? – Felix

+0

@Felix: Như tôi đã nói ở trên cùng của câu trả lời, đó là từ đặc tả ngôn ngữ (có thể được tải xuống từ www.scala-lang.org) – missingfaktor

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