2011-09-05 31 views
11

tôi đã tìm thấy mô hình này khá một vài lần trong mã của tôi:gọi có điều kiện của một phương pháp trong Scala

if (doIt) 
    object.callAMethod 
    else 
    object 

Tôi đang tự hỏi nếu có thể là một cách cú pháp dễ chịu hơn để viết mã trên, đặc biệt là để tránh sự lặp lại của biến số object. Một cái gì đó như:

// using the Scalaz "pipe" operator 
    // and "pimping" f: T => T with a `when` method 
    object |> (_.callAMethod).when(doIt) 

Thật không may dòng trên không thành công vì kiểu suy luận yêu cầu kiểu tham số cho (_.callAMethod).

tiếp cận tốt nhất của tôi bây giờ là thế này:

implicit def doItOptionally[T](t: =>T) = new DoItOptionally(t) 
    class DoItOptionally[T](t: =>T) { 
     def ?>(f: T => T)(implicit doIt: Boolean = true) = 
     if (doIt) f(t) else t 
    } 

    implicit val doIt = true 
    object ?> (_.callAMethod) 

Không tuyệt vời vì tôi phải khai báo một implicit val nhưng điều này đền đáp nếu có một số cuộc gọi xích:

 object ?> (_.callAMethod) ?> (_.callAnotherMethod) 

Có ai có một Ý tưởng tốt hơn? Tôi có thiếu ma thuật Scalaz ở đây không?

Trả lời

16
class When[A](a: A) { 
    def when(f: A => Boolean)(g: A => A) = if (f(a)) g(a) else a 
} 
implicit def whenever[A](a: A) = new When(a) 

Ví dụ:

scala> "fish".when(_.length<5)(_.toUpperCase) 
res2: java.lang.String = FISH 
+0

Tôi không nghĩ đến việc đảo ngược điều kiện và chức năng, cảm ơn! – Eric

+0

Tôi cũng nhận thấy rằng một danh từ tốt hơn ở đây so với toán tử vì '.' cần phải được sử dụng sau khi' "cá" '. – Eric

2

Tôi không thể bình luận về câu trả lời của bạn @Rex Kerr nhưng một cách ngắn gọn hơn để làm điều đó sẽ là:

implicit class When[A](a: A) { 
    def when(f: A => Boolean)(g: A => A) = if (f(a)) g(a) else a 
} 

Chỉ cần đặt trước implicit lớp này cho phép bạn bỏ qua toàn bộ hàm ẩn.

0

Nếu bạn đại diện cho callAMethod của bạn như là một endomorphism thì bạn có thể sử dụng chức năng monoid. Một cái gì đó như:

object |> valueOrZero(doIt, Endo(_.callAMethod)) 

(có thể cần một tham số kiểu trên Endo)

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