सवाल स्कैला में प्रति पैरामीटर सूचियों और एकाधिक पैरामीटर के बीच क्या अंतर है?


स्कैला में कोई इस तरह के कार्यों को लिख सकता है (करीबी?)

def curriedFunc(arg1: Int) (arg2: String) = { ... }

उपर्युक्त के बीच क्या अंतर है curriedFunc एक पैरामीटर सूची में एकाधिक पैरामीटर के साथ दो पैरामीटर सूचियों और कार्यों के साथ फ़ंक्शन परिभाषा:

def curriedFunc(arg1: Int, arg2: String) = { ... }

गणितीय दृष्टिकोण से यह है (curriedFunc(x))(y) तथा curriedFunc(x,y) लेकिन मैं लिख सकता हूँ def sum(x) (y) = x + y और वही होगा def sum2(x, y) = x + y

मुझे केवल एक अंतर पता है - यह आंशिक रूप से लागू कार्यों है। लेकिन दोनों तरीके मेरे लिए बराबर हैं।

क्या कोई और अंतर है?


76
2017-07-23 20:48


मूल




जवाब:


कड़ाई से बोलते हुए, यह एक करीबी कार्य नहीं है, लेकिन कई तर्क सूचियों वाला एक तरीका है, हालांकि स्वीकार्य रूप से यह एक समारोह की तरह दिखता है।

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

object NonCurr {
  def tabulate[A](n: Int, fun: Int => A) = IndexedSeq.tabulate(n)(fun)
}

NonCurr.tabulate[Double](10, _)            // not possible
val x = IndexedSeq.tabulate[Double](10) _  // possible. x is Function1 now
x(math.exp(_))                             // complete the application

एक अन्य लाभ यह है कि आप ब्रांड्स के बजाय घुंघराले ब्रेसिज़ का उपयोग कर सकते हैं जो कि अच्छा लगता है कि दूसरी तर्क सूची में एक ही फ़ंक्शन, या थंक होता है। जैसे

NonCurr.tabulate(10, { i => val j = util.Random.nextInt(i + 1); i - i % 2 })

बनाम

IndexedSeq.tabulate(10) { i =>
  val j = util.Random.nextInt(i + 1)
  i - i % 2
}

या थंक के लिए:

IndexedSeq.fill(10) {
  println("debug: operating the random number generator")
  util.Random.nextInt(99)
}

एक और फायदा यह है कि, आप डिफ़ॉल्ट तर्क मानों को परिभाषित करने के लिए पिछली तर्क सूची के तर्कों का उल्लेख कर सकते हैं (हालांकि आप यह भी कह सकते हैं कि यह एक नुकसान है जिसे आप एकल सूची में नहीं कर सकते :)

// again I'm not very creative with the example, so forgive me
def doSomething(f: java.io.File)(modDate: Long = f.lastModified) = ???

अंत में, संबंधित पोस्ट के जवाब में तीन अन्य आवेदन हैं स्कैला प्रति सूची एकाधिक पैरामीटर सूचियों और एकाधिक पैरामीटर दोनों क्यों प्रदान करता है? । मैं उन्हें यहां कॉपी कर दूंगा, लेकिन क्रेडिट नट आर्ने वेद, केविन राइट और एक्सटेमोर में जाता है।

पहला: आपके पास एकाधिक var args हो सकते हैं:

def foo(as: Int*)(bs: Int*)(cs: Int*) = as.sum * bs.sum * cs.sum

... जो एक तर्क सूची में संभव नहीं होगा।

दूसरा, यह प्रकार अनुमान को सहायता करता है:

def foo[T](a: T, b: T)(op: (T,T) => T) = op(a, b)
foo(1, 2){_ + _}   // compiler can infer the type of the op function

def foo2[T](a: T, b: T, op: (T,T) => T) = op(a, b)
foo2(1, 2, _ + _)  // compiler too stupid, unfortunately

और आखिरकार, यह एकमात्र तरीका है जिसके तहत आप निहित और गैर निहित तर्क प्राप्त कर सकते हैं implicit एक संपूर्ण तर्क सूची के लिए एक संशोधक है:

def gaga [A](x: A)(implicit mf: Manifest[A]) = ???   // ok
def gaga2[A](x: A, implicit mf: Manifest[A]) = ???   // not possible

81
2017-07-23 23:21



चूंकि यह सबसे अधिक वोट दिया गया जवाब है, मुझे लगता है कि प्रश्न का शीर्षक अब इसके उत्तर के अनुरूप नहीं है। मुझे लगता है कि शीर्षक को बदला जाना चाहिए, कहें, "स्कैला एकाधिक पैरामीटर सूचियों और प्रति सूची एकाधिक पैरामीटर दोनों क्यों प्रदान करता है?", यानी यह पहले से ही नमूनों द्वारा विलय कर चुका है stackoverflow.com/questions/4684185/...। - Jacek Laskowski


एक और अंतर है जो 0 __ के उत्कृष्ट द्वारा कवर नहीं किया गया था उत्तरडिफ़ॉल्ट पैरामीटर। किसी पैरामीटर सूची से डिफ़ॉल्ट पैरामीटर सूची में डिफ़ॉल्ट गणना करते समय एक पैरामीटर सूची से पैरामीटर का उपयोग किया जा सकता है, लेकिन उसी में नहीं।

उदाहरण के लिए:

def f(x: Int, y: Int = x * 2) = x + y // not valid
def g(x: Int)(y: Int = x * 2) = x + y // valid

39
2017-07-26 02:57



इसके लिए डूबने के लिए इस सरल उदाहरण को लिया। यह वास्तव में डिफ़ॉल्ट पैरामीटर को और अधिक उपयोगी बनाता है। धन्यवाद! - Mike McFarland
अच्छा उदाहरण, सिवाय इसके कि मैंने इसे कॉल करने के लिए पांच मिनट बिताए हैं: g(1)() रिटर्न 3। g(1)(2) रिटर्न 5। - Sapience


यह पूरा मुद्दा है, यह है कि करीबी और अनिश्चित रूप बराबर हैं! जैसा कि अन्य ने बताया है, एक या दूसरा रूप हो सकता है वाक्य रचना स्थिति के आधार पर काम करने के लिए और अधिक सुविधाजनक है, और यह एक दूसरे के ऊपर एक को पसंद करने का एकमात्र कारण है।

यह समझना महत्वपूर्ण है कि भले ही स्काला में करीबी कार्यों की घोषणा के लिए विशेष वाक्यविन्यास न हो, फिर भी आप उन्हें बना सकते हैं; एक बार जब आपके पास फ़ंक्शंस लौटने वाले कार्यों को बनाने की क्षमता हो तो यह केवल गणितीय अनिवार्यता है।

इसे प्रदर्शित करने के लिए, कल्पना करें कि def foo(a)(b)(c) = {...} वाक्यविन्यास मौजूद नहीं था। फिर आप अभी भी वही चीज़ प्राप्त कर सकते हैं जैसे: def foo(a) = (b) => (c) => {...}

स्कैला में कई विशेषताओं की तरह, यह कुछ ऐसा करने के लिए सिर्फ एक वाक्य रचनात्मक सुविधा है जो वैसे भी संभव होगा, लेकिन थोड़ी अधिक verbosity के साथ।


18
2017-07-23 23:18





दो रूप isomorphic हैं। मुख्य अंतर यह है कि करीबी कार्यों को आंशिक रूप से लागू करना आसान होता है, जबकि गैर-करीबी कार्यों में कम से कम स्केल में थोड़ा अच्छा सिंटैक्स होता है।


4
2017-07-23 20:55



पहले यह नहीं कहा गया है कि उदाहरण हैं नहीं करीबी काम? मैं समझता हूं कि एक करीबी फ़ंक्शन में केवल एक ही तर्क होता है और एक तर्क के साथ एक फ़ंक्शन वापस कर सकता है और तब तक जब तक सभी तर्कों के साथ कोई शरीर बंद नहीं हो जाता है। क्या मै गलत हु? - Jacek Laskowski