2011-09-05 6 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

मैं शर्त और समारोह, धन्यवाद inverting नहीं सोचा था (Endo पर एक प्रकार पैरामीटर आवश्यकता हो सकती है)! – Eric

+0

मैं भी आप देखते हैं कि संज्ञा है क्योंकि '' .' "मछली" 'के बाद इस्तेमाल किया जा करने की जरूरत है बेहतर यहाँ एक ऑपरेटर से चला जाता है। – 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 एक endomorphism तो आप monoid कार्यक्षमता का उपयोग कर सकते हैं। कुछ की तरह:

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