2011-09-05 111 views
11

的方法的條件調用我發現在我的代碼這種模式好幾次:在斯卡拉

if (doIt) 
    object.callAMethod 
    else 
    object 

我想知道是否有可能是上面寫的代碼語法上更加賞心悅目的方式,特別是爲了避免重複變量object。喜歡的東西:

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

不幸的是,線,因爲類型推斷需要(_.callAMethod)參數類型上面的失敗。

我最好現在的做法是這樣的:

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) 

不是偉大的,因爲我要申報implicit val但是如果有幾個鏈接調用此不負有心人:

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

有誰有更好的主意?我在這裏錯過了一些斯卡拉茲的魔法嗎?

回答

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) 

例子:

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

我沒想到反轉的條件和功能,感謝! – Eric

+0

我還注意到,名詞在這裏比操作符更好,因爲''.''需要在''fish''後面使用。 – Eric

2

,我不能對你的解答@Rex克爾,但更簡潔的方式做評論,這將是:

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

只把implicit前該類允許您完全省略隱式函數。

0

如果您將callAMethod表示爲自同態,則可以使用monoid功能。喜歡的東西:

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

(可能需要在Endo類型參數)