2011-09-07 17 views
5

मेरे पास एक ऋण पैटर्न है जो एक फ़ंक्शन एन बार लागू करता है जहां 'i' incrementing चर है। "कभी-कभी", मैं चाहता हूं कि समारोह 'i' तक पहुंच सके ... लेकिन मैं 'i' स्वीकार करने के लिए एक परम परिभाषित करने के लिए पारित सभी कार्यों की आवश्यकता नहीं चाहता हूं। नीचे दिए गए उदाहरण ...स्कैला ऋण पैटर्न, वैकल्पिक फ़ंक्शन पैरा

def withLoaner = (n:Int) => (op:(Int) => String) => { 
    val result = for(i <- 1 to n) yield op(i) 
    result.mkString("\n") 
} 

def bob = (x:Int) => "bob" // don't need access to i. is there a way use() => "bob" instead? 
def nums = (x:Int) => x.toString // needs access to i, define i as an input param 

println(withLoaner(3)(bob)) 

println(withLoaner(3)(nums)) 
+0

प्रश्न से संबंधित नहीं है, लेकिन यदि आप def f (args) = expr (निश्चित रूप से यह सामान्य रूप से ऐसा करेंगे) की बजाय def f: (args) => expr लिखते हैं, तो आप इसके बजाय fa val बना सकते हैं एक डीईएफ से। –

उत्तर

11
def withLoaner(n: Int) = new { 
    def apply(op: Int => String) : String = (1 to n).map(op).mkString("\n") 
    def apply(op:() => String) : String = apply{i: Int => op()} 
} 

(यकीन नहीं है कि यह कैसे ऋण पैटर्न से संबंधित है)

संपादित लिटिल टिप्पणी में अनुरोध के रूप में व्याख्या।

सुनिश्चित नहीं है कि आप क्या जानते हैं और स्कैला के बारे में नहीं जानते हैं और आप उस कोड में क्या नहीं करते हैं। तो माफ करना अगर मैं सिर्फ स्पष्ट बताता हूं।

सबसे पहले, एक स्कैला कार्यक्रम में लक्षण/कक्षाएं (सिंगलटन ऑब्जेक्ट) और विधियां भी शामिल होती हैं। जो कुछ भी किया जाता है वह विधियों द्वारा किया जाता है (कन्स्ट्रक्टर को छोड़कर)। कार्य (विधियों के विपरीत) विभिन्न FunctionN लक्षणों (एन तर्कों की संख्या) के उदाहरण (उपप्रकार) हैं। उनमें से प्रत्येक के पास लागू विधि है जो वास्तविक कार्यान्वयन है। यदि आप लिखने

val inc = {i: Int => i + 1} 

यह

val inc = new Function1[Int, Int] {def apply(i: Int) = i + 1} 

को desugared है (एक अनाम वर्ग Function1 विस्तार दिया साथ विधि और उदाहरण बनाकर लागू निरूपित करता है)

तो एक समारोह लिख बल्कि अधिक है एक साधारण विधि से वजन। इसके अलावा आप ओवरलोडिंग (उसी नाम के साथ कई विधियों, हस्ताक्षर से अलग, बस मैंने जो किया है), और न ही तर्कों का उपयोग, या तर्क के लिए डिफ़ॉल्ट मान का उपयोग कर सकते हैं।

दूसरी ओर, कार्य प्रथम कक्षा मान होते हैं (परिणाम के रूप में उन्हें तर्क के रूप में पारित किया जा सकता है, परिणाम के रूप में लौटाया जा सकता है) जबकि विधियां नहीं हैं। आवश्यकता होने पर वे स्वचालित रूप से फ़ंक्शंस में परिवर्तित हो जाते हैं, हालांकि ऐसा करने पर कुछ किनारों के मामले हो सकते हैं। यदि कोई विधि पूरी तरह से एक विधि के रूप में उपयोग करने के बजाय फ़ंक्शन मान के रूप में उपयोग करने का इरादा है, तो फ़ंक्शन लिखना बेहतर हो सकता है।

एक समारोह f, अपने apply विधि के साथ,, f(x) बजाय f.apply(x) साथ कहा जाता है (जो भी काम करता है), क्योंकि के लिए एक कॉल करने के लिए एक मूल्य (कोष्ठकों और 0 या अधिक आर्ग के बाद मूल्य) पर स्केला desugars समारोह कॉल अंकन विधि applyf(x)f.apply(x) के लिए वाक्य रचनात्मक चीनी है। यह f के प्रकार जो भी काम करता है, इसे FunctionN में से एक होने की आवश्यकता नहीं है।

लोनर के साथ क्या किया जाता है एक ऑब्जेक्ट लौटा रहा है (अज्ञात प्रकार का, लेकिन कोई एक वर्ग को अलग से परिभाषित कर सकता था और इसका एक उदाहरण लौटा सकता था)। ऑब्जेक्ट में दो apply विधियां हैं, एक Int => String स्वीकार कर रहा है, दूसरा एक () => String है। जब आप withLoaner(n)(f) करते हैं तो इसका अर्थ है withLoaner(n).apply(f)। उचित लागू विधि का चयन किया गया है, यदि f में उनमें से एक के लिए उचित प्रकार है, अन्यथा, त्रुटि संकलित करें।

बस मामले में आप withLoaner(n) आश्चर्य withLoaner.apply(n) मतलब यह नहीं है (या यह कभी नहीं बंद कर देंगे, बस के रूप में अच्छी तरह से मतलब है कि withLoaner.apply.apply(n)), के रूप में withLoaner एक विधि, नहीं एक मूल्य है।

+0

यह बहुत अच्छा लग रहा है। बहुत अच्छा। क्या आप क्या कर रहे हैं इसके बारे में थोड़ा सा स्पष्टीकरण जोड़ना चाहते हैं? साथ ही, क्या आप कह रहे हैं कि def f (args) = expr एक अधिक आम/बेहतर अभ्यास है? यकीन नहीं क्यों ... – eptx

+0

उत्कृष्ट didierd। धन्यवाद! – eptx

संबंधित मुद्दे