2011-09-29 46 views
16

Tôi mới sử dụng Scala. Tôi tự hỏi liệu nó có thể xác định một số ưu tiên với các cuộc gọi phương thức. Ví dụ, nếu tôi có chuỗi của phương pháp gọi:Scala - phương thức ưu tiên

someObject method1 param1 method2 param2 method3 param3 

này có thể tương đương như sau:

someObject.method1(param1).method2(param2.method3(param3)) 

hoặc

someObject method1 param1 method2 (param2 method3 param3) 

Vì vậy, tôi muốn method3 để được ưu tiên hơn method2 ...

Lý do tôi muốn làm điều này là tôi muốn phát triển một DSL, vì vậy tôi muốn tránh sử dụng dấu chấm và dấu ngoặc đơn càng nhiều càng tốt. Nếu các bạn tìm một giải pháp khác cho tôi, hãy cho tôi biết.

+2

Bạn có thể muốn đọc http://www.manning.com/ghosh/ (DSL trong Action) vì nó sẽ giúp giải thích rất nhiều. Ông bao gồm Ruby, Scala (chủ yếu là Scala), Clojure và Groovy. –

Trả lời

3

Hành vi này được xác định trong chương 6.12.3 Infix Operations của Đặc điểm ngôn ngữ Scala.

Tóm lại: các phương thức được gọi từ trái sang phải theo mặc định với một số ngoại lệ. Những ngoại lệ này chỉ được giới thiệu để hỗ trợ các toán tử ưu tiên toán học. Vì vậy, khi bạn có hai chức năng đặt tên *+:

a + b * c 

này sẽ luôn được dịch sang:

a.+(b.*(c)) 

Đây là tên đầu tiên của hàm điều khiển được ưu tiên. Tuy nhiên đối với các chức năng thông thường, bạn không thể kiểm soát thứ tự. Hãy suy nghĩ về nó - điều này thực sự sẽ gây ra sự phá hoại và mã không thể chấp nhận được.

Xem thêm (không hoàn toàn trùng lặp?): Operator precedence in Scala.

+1

Lưu ý rằng thông số kỹ thuật sai - xem http://article.gmane.org/gmane.comp.lang.scala/24402 và http://stackoverflow.com/questions/7022207/why-scala-changed-relative-precedence -quan hệ quan hệ-vs-bình đẳng-nhà khai thác-so sánh/7022704 # 7022704. – huynhjl

11

Bạn sẽ phải sử dụng các phương thức có ký tự điều khiển đặc biệt để ảnh hưởng đến quyền ưu tiên như ngụ ý bởi Tomasz. Đây là một phần lý do tại sao rất nhiều Scala DSL sử dụng nhiều các toán tử. Ngoài ra tại sao một số DSL khó đọc nếu bạn không làm việc với chúng hàng ngày.

Với phương pháp với chỉ sử dụng chữ, dấu gạch dưới và chữ số - bạn sẽ không thể ảnh hưởng đến mọi thứ, đây là những gì tôi đặt lại với nhau cho bản thân mình sau khi đọc spec:

  • Bất kỳ phương pháp mà phải mất một đơn tham số có thể được sử dụng như một toán tử infix: a.m(b) có thể được viết a m b.
  • Bất kỳ phương thức nào không yêu cầu tham số đều có thể được sử dụng làm toán tử postfix: a.m có thể được viết a m.

  • khai thác Postfix có độ ưu tiên thấp hơn so với các nhà khai thác ghi vào, vì vậy foo bar baz nghĩa foo.bar(baz) khi foo bar baz bam nghĩa (foo.bar(baz)).bamfoo bar baz bam bim nghĩa (foo.bar(baz)).bam(bim).

Vì vậy mà không biết chút gì về chữ ký phương pháp của bạn, đoạn mã sau (vì đó là tất cả chữ và số):

someObject method1 param1 method2 param2 method3 param3 

sẽ được phân tích như sau:

someObject.method1(param1).method2(param2).method3(param3) 

Nếu bạn đổi tên method3 đến |*| hoặc +:+ hoặc bất kỳ nhà điều hành nào có ý nghĩa, bạn có thể đạt được những gì bạn muốn:

someObject method1 param1 method2 param2 |*| param3 
// same as 
someObject.method1(param1).method2(param2.|*|(param3)) 

Ví dụ để thấy sự khác biệt:

implicit def pimp(s:String) = new { 
    def |*|(t:String) = t + s 
    def switch(t:String) = t + s 
} 

scala> "someObject" concat "param1" concat "param2" |*| "param3" 
res2: java.lang.String = someObjectparam1param3param2 

scala> "someObject" concat "param1" concat "param2" switch "param3" 
res3: java.lang.String = param3someObjectparam1param2 
+0

Câu trả lời của bạn rất hữu ích :). Nhưng tôi thực sự muốn DSL của tôi dễ hiểu và trực quan để sử dụng, vì vậy tôi không thể sử dụng các phương thức có ký tự không phải chữ và số. Có cách nào để trộn các chữ cái và các ký tự không phải chữ và số cho tên phương thức không ??? – Peter

+0

@Peter, Không theo cách hữu ích. Bạn có thể đặt tên cho phương thức 'foo_?' Hoặc 'foo _ #% ^' nhưng đó là chữ cái đầu tiên của phương thức xác định quyền ưu tiên và nếu tên phương thức bắt đầu bằng ký tự toán tử, nó phải được tạo hoàn toàn bằng ký tự toán tử. Lưu ý rằng DSL vẫn có thể trực quan nếu bạn sử dụng các ký tự đặc biệt nhưng bạn cần phải cẩn thận. Ví dụ: tôi thấy hầu hết các toán tử trong http://www.scala-lang.org/api/current/scala/sys/process/ProcessBuilder.html dễ nhớ, trong khi tôi gặp khó khăn với http: // dispatch .databinder.net/Hai + Trình xử lý + Có + Tốt hơn + Hơn + One.html. – huynhjl

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