2010-07-05 28 views
17

Tôi khá mới đối với ngôn ngữ lập trình Scala, và đang thử thứ gì đó mắc kẹt trong đầu khi đang theo dõi bài giảng tại here.Tìm hiểu về cách gọi và toán tử của phương thức infix (:) trong Scala

Tôi nghĩ rằng tôi có thể không thực sự hiểu thế nào nhược điểm điều hành hoạt động, đây là một số điều tôi đã cố gắng:

tôi đã tạo ra một bộ tạo số giả ngẫu nhiên, sau đó đã cố gắng để tạo ra một danh sách của một giá trị ngẫu nhiên:

scala> val gen = new java.util.Random 
gen: java.util.Random = [email protected] 

scala> gen nextInt 3 :: Nil 
<console>:7: error: type mismatch; 
found : List[Int] 
required: Int 
     gen nextInt 3 :: Nil 
        ^

Nhưng nó đã cố chuyển Danh sách (3) sang phương pháp tiếp theo. Khi tôi sử dụng paratheses, không có vấn đề

scala> (gen nextInt 3) :: Nil 
res69: List[Int] = List(1) 

tôi rất tò mò về thứ tự thực hiện, do đó, tôi tạo ra một chức năng để kiểm tra xem nó

scala> def pr(i:Int):Int = { println(i); i } 
pr: (i: Int)Int 

scala> pr(1) :: pr(2) :: pr(3) :: Nil 
1 
2 
3 
res71: List[Int] = List(1, 2, 3) 

Như đã thấy trong kết quả đầu ra, trình tự thực hiện cũng giống như thứ tự xuất hiện. Sau đó, tôi nghĩ rằng nó có thể là về chức năng 'nextInt', sau đó tôi đã thử theo dõi:

scala> 1 + 2 :: Nil 
res72: List[Int] = List(3) 

Bổ sung được thực thi đầu tiên và sau khi thực hiện điều đó. Vì vậy, đây là câu hỏi: Sự khác biệt giữa gen nextInt 3 :: Nil1 + 2 :: Nil là gì?

Trả lời

39

Có hai điều quan tâm ở đây: precedencefixity. Như đã đề cập, câu hỏi trên Stack Overflow giải thích quyền ưu tiên, nghĩ rằng các quy tắc, như được trích dẫn, không hoàn chỉnh đủ, và có những thay đổi rất nhỏ từ Scala 2.7 đến Scala 2.8. Sự khác biệt liên quan đến hầu hết các nhà khai thác kết thúc trong =, mặc dù.

Đối với cố định, hầu hết mọi thứ trong Scala được đọc từ trái sang phải, đó là những gì người lập trình được sử dụng. Tuy nhiên, trong Scala, các toán tử kết thúc bằng : được đọc từ phải sang trái.

Đưa, sau đó, ví dụ này:

1 + 2 :: Nil 

Thứ nhất, ưu tiên. Điều gì có quyền ưu tiên nhất, + hoặc :? Theo bảng, + được ưu tiên hơn :, vì vậy việc bổ sung được thực hiện trước tiên. Do đó, khái niệm bằng này:

((1).+(2)) :: Nil 

Bây giờ không có xung đột được ưu tiên, nhưng vì :: kết thúc bằng :, nó có một tính cố định khác nhau.Người ta đọc phải sang trái, do đó:

Nil.::((1).+(2)) 

Mặt khác, trong này:

gen nextInt 3 :: Nil 

Nhà điều hành :: có ưu tiên hơn nextInt, vì : có ưu tiên hơn tất cả các chữ cái. Do đó, và nhớ lại tính ổn định của nó, nó trở thành:

gen nextInt Nil.::(3) 

nào sau đó trở thành

gen.nextInt(Nil.::(3)) 

Tại điểm mà lỗi là rõ ràng.

PS: Tôi đang viết (1).+(2) thay vì 1.+(2) bởi vì, tại thời điểm viết bài này, 1. được hiểu là một số đôi, làm cho 1.+(2) một biểu thức trung tố thêm đôi 1,0 đến 2. Cú pháp này bị phản đối như của Scala 2.10.0, và có lẽ sẽ không có mặt trên Scala 2.11.

+0

Cảm ơn bạn đã trả lời chi tiết của bạn, nó đã cho tôi nhiều manh mối về nhiều thứ khác nữa. Nhưng tôi có thêm một câu hỏi: Trình biên dịch giải thích biểu thức trong phần mã thứ ba mà tôi đã đưa ra trong câu hỏi ban đầu của mình; về dấu ngoặc đơn? bởi vì việc sử dụng hàm pr cho thấy các thuật ngữ được thực hiện theo thứ tự từ trái sang phải. – ciuncan

+1

Đúng vậy, các cuộc gọi hàm được đánh giá từ trái sang phải. Đó là bởi vì 'pr (X)' là các biểu thức đối số của '::' và chúng được đánh giá đầu tiên theo thứ tự xuất hiện và sau đó giá trị được truyền cho phương thức. 'pr (1) :: pr (2) :: pr (3) :: Nil' in 1 2 3. Nhưng' Nil.::(pr(3)).::(pr(2)). :: (pr (1)) 'in 3 2 1. Nhưng cả hai đều trả về' Danh sách (1, 2, 3) ' –

+0

@ciuncan Tôi không biết. Nó có thể là ký hiệu toán tử với đúng fixity cho phép một thứ tự đánh giá không thể với dấu chấm, hoặc nó có thể là trình biên dịch tối ưu hóa '::' cuộc gọi nhưng có một lỗi liên quan đến đánh giá thứ tự. –

3

Đó là ưu tiên không theo thứ tự thực hiện. + có mức độ ưu tiên cao hơn ::, do đó, a + b :: c phân tích cú pháp là (a + b) :: c. Tuy nhiên, các cuộc gọi phương thức infix với tên thông thường có mức ưu tiên thấp hơn, do đó, a foo b c phân tích cú pháp là a foo (b c).

Xem this question để biết danh sách các toán tử được sắp xếp theo mức ưu tiên của họ trong scala.

+1

Cảm ơn bạn đã giải thích. Ưu tiên là những gì tôi chỉ nghĩ đến. – ciuncan

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