Scala में कई मापदंडों की सूची और प्रति सूची के कई मापदंडों के बीच अंतर क्या है?


81

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

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

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

क्या कोई अन्य मतभेद हैं?

जवाबों:


88

कड़ाई से बोलना, यह एक क्यूरेटेड फ़ंक्शन नहीं है, लेकिन कई तर्क सूचियों के साथ एक विधि है, हालांकि माना जाता है कि यह एक फ़ंक्शन की तरह दिखता है।

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

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

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

42

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

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

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

इसमें डूबने के लिए यह सरल उदाहरण लिया। यह वास्तव में डिफ़ॉल्ट मापदंडों को अधिक उपयोगी बनाता है। धन्यवाद!
माइक मैकरलैंड

अच्छा उदाहरण, सिवाय इसके कि मैं इसे कॉल करने का तरीका जानने के लिए पाँच मिनट बिताता हूँ: g(1)()रिटर्न 3. g(1)(2)रिटर्न 5.
Sapience

19

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

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

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

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


4

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


2
क्या यह पहले नहीं कहा गया है कि उदाहरणों में करीने वाले कार्य नहीं हैं ? मैं समझता हूं कि एक करीने वाले फ़ंक्शन में केवल एक तर्क होता है और एक फ़ंक्शन को एक तर्क के साथ वापस कर सकता है और इसी तरह जब तक कि सभी तर्कों के साथ एक निकाय बंद न हो जाए। क्या मै गलत हु?
जसक लस्कॉस्की
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.