Ing करी ’क्या है?


652

मैंने कई लेखों और ब्लॉगों में करी कार्यों के संदर्भ देखे हैं, लेकिन मुझे एक अच्छी व्याख्या नहीं मिल रही है (या कम से कम एक जो समझ में आता है!)


12
[एक टिप्पणी के रूप में छोड़ दिया, क्योंकि यह गैर-गणितज्ञों के लिए बेकार होगा।] कार्टेशियन बंद श्रेणी की परिभाषा के अनुसार, एक्स - एक्स एक्स ए और एक्स के बीच एक निश्चित परिवार का एक निश्चित परिवार है (स्वाभाविक रूप से ए द्वारा ए)। -> X ^ A. आइसोमॉर्फिम्स होम (X x A, Y) <-> होम (X, Y ^ A) हास्केल के कार्य curryऔर uncurryकार्य हैं। यहाँ जो महत्वपूर्ण है वह यह है कि ये समसामयिकता पहले से तय की जाती है, और इसलिए भाषा में "अंतर्निहित" है।
एलेक्जेंडर सी।

3
वहाँ एक अच्छा ट्यूटोरियल यहाँ हास्केल में currying के लिए है learnyouahaskell.com/higher-order-functions#curried-functions कम टिप्पणी है कि है add x y = x+y(curried) के लिए अलग है add (x, y)=x+y(uncurried)
Jaider

जवाबों:


872

जब आप एक फ़ंक्शन को तोड़ते हैं, तो कई सारे फ़ंक्शंस में कई तर्क होते हैं, जिनमें से प्रत्येक केवल एक तर्क लेता है। यहाँ जावास्क्रिप्ट में एक उदाहरण है:

function add (a, b) {
  return a + b;
}

add(3, 4); // returns 7

यह एक ऐसा फंक्शन है जो दो तर्क, एक और बी लेता है, और उनकी राशि लौटाता है। अब हम इस समारोह में करी करेंगे:

function add (a) {
  return function (b) {
    return a + b;
  }
}

यह एक फ़ंक्शन है जो एक तर्क लेता है, और एक फ़ंक्शन देता है जो एक और तर्क लेता है, बी, और वह फ़ंक्शन उनकी राशि लौटाता है।

add(3)(4);

var add3 = add(3);

add3(4);

पहला स्टेटमेंट 7 जोड़ता है, जैसे ऐड (3, 4) स्टेटमेंट। दूसरा कथन add3 नामक एक नए फ़ंक्शन को परिभाषित करता है जो इसके तर्क में 3 जोड़ देगा। इसे कुछ लोग क्लोजर कह सकते हैं। तीसरा कथन 3 से 4 को जोड़ने के लिए add3 ऑपरेशन का उपयोग करता है, फिर से परिणामस्वरूप 7 का उत्पादन करता है।


235
व्यावहारिक अर्थ में, मैं इस अवधारणा का उपयोग कैसे कर सकता हूं?
स्ट्रॉबेरी

43
@ स्ट्राबेरी, उदाहरण के लिए कहें कि आपके पास संख्याओं की एक सूची है [1, 2, 3, 4, 5]जिसमें आप एक मनमानी संख्या से गुणा करना चाहते हैं। हास्केल में, मैं map (* 5) [1, 2, 3, 4, 5]पूरी सूची को गुणा करने के लिए लिख सकता हूं 5, और इस प्रकार सूची तैयार कर सकता हूं [5, 10, 15, 20, 25]
nyson

62
मैं समझता हूं कि मैप फ़ंक्शन क्या करता है, लेकिन मुझे यकीन नहीं है कि अगर मैं उस बिंदु को समझता हूं जो आप मेरे लिए वर्णन करने की कोशिश कर रहे हैं। क्या आप कह रहे हैं कि मानचित्र कार्य करी की अवधारणा का प्रतिनिधित्व करता है?
स्ट्रॉबेरी

78
@ स्ट्राबेरी पहला तर्क mapएक फ़ंक्शन होना चाहिए जो केवल 1 तर्क लेता है - सूची से एक तत्व। गुणन - एक गणितीय अवधारणा के रूप में - एक बाइनरी ऑपरेशन है; यह 2 तर्क लेता है। हालांकि, हास्केल *एक करी फ़ंक्शन है, addजो इस उत्तर के दूसरे संस्करण के समान है । परिणाम (* 5)एक ऐसा कार्य है जो एकल तर्क लेता है और इसे 5 से गुणा करता है, और यह हमें मानचित्र के साथ इसका उपयोग करने की अनुमति देता है।
डोभाल

26
@ स्ट्राबेरी मानक एमएल या हास्केल जैसी कार्यात्मक भाषाओं के बारे में अच्छी बात यह है कि आप "मुफ्त में" करी पा सकते हैं। आप एक बहु-तर्क फ़ंक्शन को परिभाषित कर सकते हैं जैसा कि आप किसी अन्य भाषा में करेंगे, और आप अपने आप को इसका एक घुमावदार संस्करण प्राप्त कर सकते हैं, बिना लैम्बदास के एक झुंड में फेंकने के लिए। तो आप नए कार्यों का उत्पादन कर सकते हैं जो किसी भी मौजूदा फ़ंक्शन से बहुत उपद्रव या परेशान किए बिना कम तर्क लेते हैं, और इससे उन्हें अन्य कार्यों के लिए पारित करना आसान हो जाता है।
डोभाल

125

कार्यों के एक बीजगणित में, ऐसे कार्यों से निपटना जो कई तर्क लेते हैं (या समतुल्य एक तर्क जो कि एक एन-टपल है) कुछ हद तक असंगत है - लेकिन, जैसा कि मूसा शॉनफिंकेल (और, स्वतंत्र रूप से, हास्केल करी ने साबित किया है: यह आवश्यक नहीं है: आप सभी की जरूरत नहीं है: आवश्यकता वे कार्य हैं जो एक तर्क लेते हैं।

तो आप स्वाभाविक रूप से व्यक्त होने वाली किसी चीज़ के साथ कैसे व्यवहार करते हैं, कहते हैं f(x,y),? ठीक है, आप बराबर के रूप में है कि ले f(x)(y)- f(x), इसे कहतेg , एक समारोह है, और आप के लिए है कि समारोह लागू y। दूसरे शब्दों में, आपके पास केवल एक तर्क लेने वाले कार्य हैं - लेकिन उन कार्यों में से कुछ अन्य कार्यों को वापस कर देते हैं (जो कि एक तर्क भी लेते हैं; ;-)

हमेशा की तरह, विकिपीडिया के पास इस बारे में एक अच्छा सारांश है, जिसमें कई उपयोगी संकेत हैं (शायद आपके पसंदीदा फोटोग्राफरों के बारे में;; साथ ही साथ थोड़ा और अधिक कठोर गणितीय उपचार।


1
मुझे लगता है कि मेरे ऊपर भी ऐसी ही टिप्पणी है - मैंने यह नहीं देखा है कि कार्यात्मक भाषाएं एक एकल arg लेने के लिए कार्यों को प्रतिबंधित करती हैं। क्या मैं गलत हूं?
एरिक एम

1
@होओ: कार्यात्मक भाषा आम तौर पर कार्यों को एक तर्क तक सीमित नहीं करती है। हालांकि, कम, अधिक गणितीय स्तर पर यह उन कार्यों से निपटने के लिए बहुत आसान है जो केवल एक तर्क लेते हैं। (लैम्ब्डा कैलकुलस में, उदाहरण के लिए, फ़ंक्शंस एक समय में केवल एक तर्क लेते हैं।)
सैम डेफेबिया-केन

1
ठीक। एक और सवाल। निम्नलिखित एक सही कथन है? लैम्ब्डा कैलकुलस को फंक्शनल प्रोग्रामिंग के मॉडल के रूप में इस्तेमाल किया जा सकता है लेकिन फंक्शनल प्रोग्रामिंग को लैम्ब्डा कैलकुलस नहीं लगाया जाता है।
एरिक एम

7
जैसा कि विकिपीडिया पृष्ठ नोट करते हैं, ज्यादातर एफपी भाषाएं "अलंकृत" या "संवर्धित" लंबा कैलकुलस (जैसे कुछ स्थिरांक और डेटाटाइप्स के साथ) केवल इसे "लागू" करने के बजाय, लेकिन यह उतना करीब नहीं है। BTW, क्या आपको यह आभास देता है कि जैसे हास्केल DOESN'T "कार्यों को एक एकल arg लेने के लिए प्रतिबंधित करता है"? यह निश्चित रूप से करता है, हालांकि यह करी के लिए अप्रासंगिक है; उदाहरण div :: Integral a => a -> a -> a- उन कई तीरों को नोट करें? "मैप अ टू फंक्शन मैपिंग टू ए" एक रीडिंग है ;-)। आप & c के लिए एक (एकल) टपल तर्क का उपयोग कर सकते हैं div, लेकिन यह वास्तव में हास्केल में मुहावरेदार विरोधी होगा।
एलेक्स मार्टेली

@ एलेक्स - एचटी हास्केल और एर्ग काउंट, मैंने हास्केल पर बहुत समय नहीं बिताया है, और यह कुछ हफ्ते पहले था। इसलिए इसे बनाना एक आसान त्रुटि थी।
एरिक एम

100

यहाँ एक ठोस उदाहरण दिया गया है:

मान लीजिए कि आपके पास एक फ़ंक्शन है जो किसी वस्तु पर कार्य करने वाले गुरुत्वाकर्षण बल की गणना करता है। यदि आप सूत्र नहीं जानते हैं, तो आप इसे यहां पा सकते हैं । यह फ़ंक्शन तर्कों के रूप में तीन आवश्यक मापदंडों को लेता है।

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


2
एक जिज्ञासा के रूप में, जावास्क्रिप्ट के लिए प्रोटोटाइप लाइब्रेरी एक "करी" फ़ंक्शन प्रदान करता है, जो आपके द्वारा यहां बताए गए कार्यों को बहुत सटीक रूप से करता है: prototypejs.org/api/function/curry
shuckster

नई प्रोटोटाइप क्युरी फंक्शन लिंक। prototypjs.org/doc/latest/language/Function/prototype/curry/…
रिचर्ड अयोटे

7
यह मुझे आंशिक अनुप्रयोग की तरह लगता है। मेरी समझ यह है कि यदि आप क्यूरिंग लागू करते हैं, तो आप एक ही तर्क के साथ कार्य बना सकते हैं और उन्हें और अधिक जटिल कार्य बनाने के लिए रचना कर सकते हैं। क्या मैं कुछ भूल रहा हूँ?
नेणतापिर

9
@neontapir सही है। शिया ने जो बताया वह करी नहीं गई। यह आंशिक अनुप्रयोग है। यदि एक तीन-तर्क फ़ंक्शन परिलक्षित होता है और आप इसे f (1) कहते हैं, तो आपको जो वापस मिलता है वह दो-तर्क फ़ंक्शन नहीं है। आपको एक-तर्क फ़ंक्शन वापस मिलता है जो एक और एक-तर्क फ़ंक्शन देता है। एक क्यूरेटेड फ़ंक्शन को केवल एक तर्क दिया जा सकता है। PrototypJS में करी फ़ंक्शन भी करी नहीं है। यह आंशिक अनुप्रयोग है।
माइंडजुइस

नहीं (आंशिक मूल्यांकन के लिए) और नहीं (करी के लिए)। इसे आंशिक अनुप्रयोग के रूप में जाना जाता है। इसे सक्षम करने के लिए करी की आवश्यकता होती है।
विल नेस

47

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

उदाहरण के लिए, F # में आप एक फंक्शन को परिभाषित कर सकते हैं: -

let f x y z = x + y + z

यहाँ फ़ंक्शन f पैरामीटर्स x, y और z लेता है और उन्हें एक साथ जोड़ देता है:

f 1 2 3

लौटता है ६।

इसलिए हम अपनी परिभाषा से f के लिए करी फ़ंक्शन को परिभाषित कर सकते हैं: -

let curry f = fun x -> f x

जहां 'फन एक्स -> एफएक्स' सी # में एक्स => एफ (एक्स) के लिए एक लंबो फ़ंक्शन है। यह फ़ंक्शन उस फ़ंक्शन को इनपुट करता है जिसे आप करी करना चाहते हैं और एक फ़ंक्शन लौटाता है जो एकल तर्क लेता है और इनपुट तर्क के लिए पहले तर्क के साथ निर्दिष्ट फ़ंक्शन देता है।

हमारे पिछले उदाहरण का उपयोग करके हम f की एक करी प्राप्त कर सकते हैं: -

let curryf = curry f

हम निम्नलिखित कर सकते हैं: -

let f1 = curryf 1

जो हमें एक फ़ंक्शन f1 प्रदान करता है जो f1 yz = 1 + y + z के बराबर है। इसका मतलब है कि हम निम्नलिखित कर सकते हैं: -

f1 2 3

जो ६।

यह प्रक्रिया अक्सर 'आंशिक फ़ंक्शन अनुप्रयोग' के साथ भ्रमित होती है जिसे इस प्रकार परिभाषित किया जा सकता है: -

let papply f x = f x

यद्यपि हम इसे एक से अधिक मापदंडों तक बढ़ा सकते हैं, अर्थात: -

let papply2 f x y = f x y
let papply3 f x y z = f x y z
etc.

एक आंशिक अनुप्रयोग फ़ंक्शन और पैरामीटर (ओं) को ले जाएगा और एक फ़ंक्शन लौटाएगा जिसमें एक या अधिक कम पैरामीटर की आवश्यकता होती है, और जैसा कि पिछले दो उदाहरण शो सीधे मानक F # फ़ंक्शन परिभाषा में लागू किया जाता है ताकि हम पिछले परिणाम को प्राप्त कर सकें: -

let f1 = f 1
f1 2 3

जो 6 के परिणाम को लौटाएगा।

निष्कर्ष के तौर पर:-

करी और आंशिक फ़ंक्शन अनुप्रयोग के बीच अंतर यह है कि: -

करीयन एक फ़ंक्शन लेता है और एक एकल तर्क को स्वीकार करते हुए एक नया फ़ंक्शन प्रदान करता है, और उस तर्क पर सेट किए गए अपने पहले तर्क के साथ निर्दिष्ट फ़ंक्शन को वापस करता है। यह हमें एकल तर्क कार्यों की एक श्रृंखला के रूप में कई मापदंडों के साथ कार्यों का प्रतिनिधित्व करने की अनुमति देता है । उदाहरण:-

let f x y z = x + y + z
let curryf = curry f
let f1 = curryf 1
let f2 = curryf 2
f1 2 3
6
f2 1 3
6

आंशिक फ़ंक्शन अनुप्रयोग अधिक प्रत्यक्ष है - यह एक फ़ंक्शन और एक या अधिक तर्क लेता है और निर्दिष्ट n तर्कों पर सेट पहले n तर्कों के साथ एक फ़ंक्शन देता है। उदाहरण:-

let f x y z = x + y + z
let f1 = f 1
let f2 = f 2
f1 2 3
6
f2 1 3
6

इससे पहले कि वे आंशिक रूप से लागू किए जा सकते हैं, इसलिए C # में तरीकों की आवश्यकता होगी?
cdmckay

"यह हमें एकल तर्क कार्यों की एक श्रृंखला के रूप में कई मापदंडों के साथ कार्यों का प्रतिनिधित्व करने की अनुमति देता है" - एकदम सही, जिसने मुझे सभी के लिए अच्छी तरह से मंजूरी दे दी। धन्यवाद
फजी विश्लेषण

44

यह अन्य कार्यों को करने के लिए फ़ंक्शंस का उपयोग करने का एक तरीका हो सकता है।

जावास्क्रिप्ट में:

let add = function(x){
  return function(y){ 
   return x + y
  };
};

हमें इसे इस तरह से कॉल करने की अनुमति देगा:

let addTen = add(10);

जब यह रन के 10रूप में पारित किया जाता है x;

let add = function(10){
  return function(y){
    return 10 + y 
  };
};

जिसका मतलब है कि हम इस समारोह में लौटे हैं:

function(y) { return 10 + y };

तो जब तुम बुलाओगे

 addTen();

आप वास्तव में फोन कर रहे हैं:

 function(y) { return 10 + y };

तो अगर आप ऐसा करते हैं:

 addTen(4)

यह इस प्रकार है:

function(4) { return 10 + 4} // 14

इसलिए addTen()हम जो भी पास करते हैं, उसमें हमेशा दस जोड़ते हैं। हम इसी तरह से समान कार्य कर सकते हैं:

let addTwo = add(2)       // addTwo(); will add two to whatever you pass in
let addSeventy = add(70)  // ... and so on...

अब स्पष्ट अनुवर्ती प्रश्न यह है कि पृथ्वी पर आप कभी ऐसा क्यों करना चाहेंगे? यह पता चलता है कि एक उत्सुक ऑपरेशन क्या था जिसे x + yआलसी के माध्यम से आगे बढ़ाया जा सकता है, जिसका अर्थ है कि हम कम से कम दो चीजें कर सकते हैं। 1. महंगा ऑपरेशन 2. कार्यात्मक प्रतिमान में सार प्राप्त करना।

हमारे करी समारोह की कल्पना इस तरह दिखी:

let doTheHardStuff = function(x) {
  let z = doSomethingComputationallyExpensive(x)
  return function (y){
    z + y
  }
}

हम इस फ़ंक्शन को एक बार कॉल कर सकते हैं, फिर परिणाम को बहुत सारे स्थानों पर उपयोग करने के लिए पास कर सकते हैं, जिसका अर्थ है कि हम केवल कम्प्यूटेशनल रूप से सामान की आपूर्ति करते हैं:

let finishTheJob = doTheHardStuff(10)
finishTheJob(20)
finishTheJob(30)

हम एक समान तरीके से सार प्राप्त कर सकते हैं।


5
एक अंतर्निहित अनुक्रमिक प्रक्रिया के चरण स्पष्टीकरण से सबसे अच्छा कदम मैंने यहाँ देखा है, और शायद सबसे अच्छा, बहुत का सबसे व्याख्यात्मक उत्तर।

4
@jonsilver मैं इसके विपरीत कहूंगा, अच्छी व्याख्या नहीं। मैं मानता हूँ कि उदाहरण के बारे में समझाने में यह अच्छा है, लेकिन लोग यह सोचकर चूक जाते हैं, "हाँ बिलकुल स्पष्ट है, लेकिन मैं उसी तरह से एक और काम कर सकता था, इसलिए क्या अच्छा है?" दूसरे शब्दों में, मैं चाहता हूं कि यह केवल पर्याप्त संदर्भ या स्पष्टीकरण था कि प्रकाश कैसे न केवल कैसे काम करता है, बल्कि यह भी है कि दस जोड़ने के अन्य तरीकों की तुलना में यह बेकार और तुच्छ अवलोकन क्यों नहीं है।
व्हाइटनीलैंड

29

एक क्यूरेटेड फंक्शन कई तर्कों का एक फ़ंक्शन होता है, जिसे फिर से लिखा जाता है ताकि यह पहले तर्क को स्वीकार करे और एक ऐसा फ़ंक्शन लौटाए जो दूसरा तर्क स्वीकार करता है और इसी तरह। यह कई तर्कों के कार्यों को उनके कुछ प्रारंभिक तर्कों को आंशिक रूप से लागू करने की अनुमति देता है।


5
"यह कई तर्कों के कार्यों को आंशिक रूप से लागू करने के लिए उनके कुछ प्रारंभिक तर्कों को अनुमति देता है।" - यह क्यों फायदेमंद है?
एसरालोन

5
@acarlon फ़ंक्शंस को अक्सर एक या अधिक तर्कों के साथ बार-बार कहा जाता है। उदाहरण के लिए, यदि आप उन सूचियों की सूची पर mapकार्य करना चाहते हैं जो आप कर सकते हैं । fxssmap (map f) xss
जॉन हैरोप

1
धन्यवाद, यह समझ में आता है। मैंने थोड़ा और पढ़ा और यह जगह में गिर गया।
एक्रालोन

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

7

यहाँ अजगर में एक खिलौना उदाहरण है:

>>> from functools import partial as curry

>>> # Original function taking three parameters:
>>> def display_quote(who, subject, quote):
        print who, 'said regarding', subject + ':'
        print '"' + quote + '"'


>>> display_quote("hoohoo", "functional languages",
           "I like Erlang, not sure yet about Haskell.")
hoohoo said regarding functional languages:
"I like Erlang, not sure yet about Haskell."

>>> # Let's curry the function to get another that always quotes Alex...
>>> am_quote = curry(display_quote, "Alex Martelli")

>>> am_quote("currying", "As usual, wikipedia has a nice summary...")
Alex Martelli said regarding currying:
"As usual, wikipedia has a nice summary..."

(गैर पायथन प्रोग्रामर के लिए व्याकुलता से बचने के लिए बस + के माध्यम से संघटन का उपयोग करना।)

जोड़ने का संपादन:

Http://docs.python.org/library/functools.html?highlight=partial#functools.partial देखें , जो आंशिक वस्तु बनाम फ़ंक्शन भेद को दर्शाता है जिस तरह से पायथन इसे लागू करता है।


मुझे यह नहीं मिलता है - आप ऐसा करते हैं: >>> am_quote = करी (डिस्प्ले_क्वाइट, "एलेक्स मार्टेली") लेकिन फिर आप इसे आगे करते हैं: >>> am_quote ("करी", "हमेशा की तरह, wippipedia का एक अच्छा सारांश है।" .. ") तो आपके पास दो आर्ग के साथ एक फ़ंक्शन है। ऐसा लगता है कि करीने से आपको तीन अलग-अलग फंक देने चाहिए जो आप रचना करेंगे?
एरिक एम

मैं केवल एक पैरामीटर करी का उपयोग कर रहा हूं, दो आर्ग के साथ एक फ़ंक्शन का निर्माण कर रहा हूं। यदि आप चाहते हैं, तो आप एक विषय बनाने के लिए am_quote को आगे बढ़ा सकते हैं जो केवल एलेक्स को किसी विशेष विषय पर उद्धृत करता है। गणित बैकगाउंड केवल एक पैरामीटर के साथ कार्यों को समाप्त करने पर केंद्रित हो सकता है - लेकिन मेरा मानना ​​है कि इस तरह के किसी भी पैरामीटर को ठीक करना आम तौर पर (अगर गणित के दृष्टिकोण से असंभव है) जिसे करी कहा जाता है।
दोपहर

(btw - '>>>' पायथन इंटरएक्टिव दुभाषिया में संकेत है, कोड का हिस्सा नहीं है।)
Anon

Args के बारे में स्पष्टीकरण के लिए ठीक है धन्यवाद। मैं पायथन दुभाषिया संकेत के बारे में जानता हूं, मैं लाइनों को उद्धृत करने की कोशिश कर रहा था, लेकिन यह काम नहीं करता ;-)
एरिक एम

आपकी टिप्पणी के बाद, मैंने "करी" और "के बीच के अंतर" के लिए एसओ सहित अन्य संदर्भों को खोजा और पाया। "आंशिक अनुप्रयोग" के उपयोग के बहुत से उदाहरणों के जवाब में मैं परिचित हूं। उदाहरण के लिए देखें: stackoverflow.com/questions/218025/…
Anon

5

करी कॉल करने योग्य के रूप f(a, b, c)में के रूप में callable से एक समारोह का अनुवाद है f(a)(b)(c)

अन्यथा क्यूरिंग तब होती है जब आप एक फ़ंक्शन को तोड़ते हैं जो कई तर्कों को कई कार्यों में ले जाता है जो तर्कों का हिस्सा होते हैं।

शाब्दिक रूप से, करी करना कार्यों का एक परिवर्तन है: कॉलिंग के एक तरीके से दूसरे में। जावास्क्रिप्ट में, हम आम तौर पर मूल फ़ंक्शन रखने के लिए एक आवरण बनाते हैं।

करी एक फ़ंक्शन को कॉल नहीं करती है। यह सिर्फ उसे बदल देता है।

चलो करी फ़ंक्शन बनाते हैं जो दो-तर्क कार्यों के लिए करी करता है। दूसरे शब्दों में, curry(f)दो-तर्क के लिए f(a, b)इसका अनुवाद किया जाता हैf(a)(b)

function curry(f) { // curry(f) does the currying transform
  return function(a) {
    return function(b) {
      return f(a, b);
    };
  };
}

// usage
function sum(a, b) {
  return a + b;
}

let carriedSum = curry(sum);

alert( carriedSum(1)(2) ); // 3

जैसा कि आप देख सकते हैं, कार्यान्वयन आवरणों की एक श्रृंखला है।

  • परिणाम curry(func)एक आवरण हैfunction(a)
  • जब इसे कहा जाता है sum(1), तो तर्क को लेक्सिकल पर्यावरण में सहेजा जाता है, और एक नया आवरण वापस किया जाता हैfunction(b)
  • फिर sum(1)(2)अंत में function(b)2 प्रदान करने वाले कॉल , और यह कॉल को मूल बहु-तर्क योग में पास करता है।

4

यदि आप समझते हैं कि partialआप आधे रास्ते में हैं। विचार partialयह है कि किसी फ़ंक्शन के लिए तर्कों का प्रचार करना और एक नया फ़ंक्शन वापस देना है जो केवल शेष तर्क चाहता है। जब इस नए फ़ंक्शन को कहा जाता है, तो इसमें पहले से लोड किए गए तर्कों के साथ-साथ जो भी तर्क दिए गए थे, उसमें शामिल हैं।

क्लोजर +एक फ़ंक्शन है लेकिन चीजों को स्पष्ट रूप से स्पष्ट करने के लिए:

(defn add [a b] (+ a b))

आप इस बात से अवगत हो सकते हैं कि incफ़ंक्शन केवल 1 को जो भी संख्या उत्तीर्ण करता है, जोड़ता है।

(inc 7) # => 8

चलो इसे स्वयं का उपयोग करके बनाते हैं partial:

(def inc (partial add 1))

यहां हम एक और फ़ंक्शन लौटाते हैं जिसमें 1 को पहले तर्क में लोड किया गया है addaddदो तर्कों के रूप में नया incफ़ंक्शन केवल bतर्क चाहता है - 2 तर्क नहीं, क्योंकि 1 से पहले ही आंशिक रूप से लागू किया गया है। इस प्रकार partialएक ऐसा उपकरण है जिससे डिफ़ॉल्ट मानों के साथ नए कार्य बनाए जा सकते हैं। यही कारण है कि एक कार्यात्मक भाषा कार्यों में अक्सर सामान्य से विशिष्ट तक के तर्क दिए जाते हैं। इससे ऐसे कार्यों का पुन: उपयोग करना आसान हो जाता है जिनसे अन्य कार्यों का निर्माण किया जाता है।

अब कल्पना कीजिए कि क्या भाषा इतनी स्मार्ट थी कि अंतरात्मा को समझने के लिए addदो तर्क चाहिए। जब हमने इसे एक तर्क के रूप में पारित किया, बजाए इसके कि, क्या होगा यदि फ़ंक्शन ने आंशिक रूप से उस तर्क को लागू किया जिसे हमने अपनी ओर से यह समझकर पारित किया कि हम संभवतः दूसरे तर्क प्रदान करने के लिए हैं? हम incस्पष्ट रूप से उपयोग किए बिना परिभाषित कर सकते हैं partial

(def inc (add 1)) #partial is implied

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


3

मुझे यह लेख, और यह लेख संदर्भ, उपयोगी, करीने को बेहतर ढंग से समझने के लिए उपयोगी मिला: http://blogs.msdn.com/wesdyer/archive/2007/01/29/currying-and-partial-function-application.aspx

जैसा कि दूसरों ने उल्लेख किया है, यह एक पैरामीटर फ़ंक्शन करने का एक तरीका है।

यह उपयोगी है कि आपको यह मानने की ज़रूरत नहीं है कि कितने पैरामीटर पास किए जाएंगे, इसलिए आपको 2 पैरामीटर, 3 पैरामीटर और 4 पैरामीटर फ़ंक्शन की आवश्यकता नहीं है।


3

अन्य सभी उत्तरों के रूप में करीने से आंशिक रूप से लागू कार्यों को बनाने में मदद मिलती है। जावास्क्रिप्ट स्वत: करी के लिए मूल समर्थन प्रदान नहीं करता है। तो ऊपर दिए गए उदाहरण व्यावहारिक कोडिंग में मदद नहीं कर सकते हैं। जीवनशैली में कुछ उत्कृष्ट उदाहरण हैं (जो अनिवार्य रूप से js के लिए संकलित हैं) http://livescript.net/

times = (x, y) --> x * y
times 2, 3       #=> 6 (normal use works as expected)
double = times 2
double 5         #=> 10

ऊपर दिए गए उदाहरण में जब आपने कोई तर्क नहीं दिया है तो जीवनशैली आपके लिए नया करी फ़ंक्शन तैयार करती है (डबल)


3

करी आपके कोड को सरल बना सकती है। यह इसका उपयोग करने के मुख्य कारणों में से एक है। करीकरण एक फ़ंक्शन को परिवर्तित करने की एक प्रक्रिया है जो एन तर्कों को एन कार्यों में स्वीकार करता है जो केवल एक तर्क को स्वीकार करते हैं।

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

इसका लाभ यह है कि यह एक समय में एक पैरामीटर से निपटकर मापदंडों के प्रसंस्करण को सरल बना सकता है, जिससे कार्यक्रम के लचीलेपन और पठनीयता में भी सुधार हो सकता है। यह भी प्रोग्राम को अधिक प्रबंधनीय बनाता है। इसके अलावा कोड को छोटे टुकड़ों में विभाजित करने से यह पुन: उपयोग के अनुकूल हो जाएगा।

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

function curryMinus(x) 
{
  return function(y) 
  {
    return x - y;
  }
}

var minus5 = curryMinus(1);
minus5(3);
minus5(5);

मैं भी कर सकता हूँ ...

var minus7 = curryMinus(7);
minus7(3);
minus7(5);

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


2

एक तर्कपूर्ण फ़ंक्शन को केवल एक के बजाय कई तर्क सूचियों पर लागू किया जाता है।

यहां एक नियमित, गैर-करीबी फ़ंक्शन है, जो दो इंट पैरामीटर जोड़ता है, x और y:

scala> def plainOldSum(x: Int, y: Int) = x + y
plainOldSum: (x: Int,y: Int)Int
scala> plainOldSum(1, 2)
res4: Int = 3

यहाँ समान फ़ंक्शन है जो करी गई है। दो इंट मापदंडों की एक सूची के बजाय, आप इस फ़ंक्शन को एक इंट पैरामीटर के दो सूचियों पर लागू करते हैं:

scala> def curriedSum(x: Int)(y: Int) = x + y
curriedSum: (x: Int)(y: Int)Intscala> second(2)
res6: Int = 3
scala> curriedSum(1)(2)
res5: Int = 3

यहाँ क्या हो रहा है कि जब आप आह्वान करते हैं curriedSum, तो आपको वास्तव में दो पारंपरिक फ़ंक्शन चालान वापस मिल जाते हैं। पहला फ़ंक्शन मंगलाचरण नाम का एक एकल Int पैरामीटर लेता है x, और दूसरे फ़ंक्शन के लिए फ़ंक्शन मान देता है। यह दूसरा फ़ंक्शन Int पैरामीटर लेता है y

यहां एक फ़ंक्शन का नाम दिया firstगया है जो आत्मा में करता है कि पहले पारंपरिक फ़ंक्शन का आह्वान curriedSumक्या करेगा:

scala> def first(x: Int) = (y: Int) => x + y
first: (x: Int)(Int) => Int

1 को पहले फ़ंक्शन में लागू करना - दूसरे शब्दों में, पहले फ़ंक्शन को लागू करना और 1 में गुजरना - दूसरा फ़ंक्शन:

scala> val second = first(1)
second: (Int) => Int = <function1>

2 से दूसरे फंक्शन में जाने से परिणाम मिलता है:

scala> second(2)
res6: Int = 3

2

करीने का एक उदाहरण तब होगा जब आपके पास केवल एक ही कार्य हो, जो उस समय किसी एक पैरामीटर को जानता हो:

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

func aFunction(str: String) {
    let callback = callback(str) // signature now is `NSData -> ()`
    performAsyncRequest(callback)
}

func callback(str: String, data: NSData) {
    // Callback code
}

func performAsyncRequest(callback: NSData -> ()) {
    // Async code that will call callback with NSData as parameter
}

यहाँ, जब से आप कॉलबैक के लिए दूसरा पैरामीटर नहीं जानते हैं, performAsyncRequest(_:)तो आपको इसे भेजने के लिए एक और लंबा / क्लोजर बनाना होगा ताकि उस फ़ंक्शन को भेजा जा सके।


है func callbackही लौटने? यह कहा जा रहा है @ callback(str)इसलिए let callback = callback(str), कॉलबैक का सिर्फ वापसी मान हैfunc callback
Nikk वोंग

नहीं, func callback(_:data:)दो मापदंडों को स्वीकार करता है, यहां मैं केवल इसे एक देता हूं String, इसलिए यह अगले एक ( NSData) का इंतजार कर रहा है , यही कारण है कि अब let callbackएक और फ़ंक्शन डेटा के पारित होने की प्रतीक्षा कर रहा है
S2dent

2

यहाँ जे नं के साथ फ़ंक्शन करी के लिए सामान्य और सबसे छोटा संस्करण का उदाहरण है। परम के।

const add = a => b => b ? add(a + b) : a; 

const add = a => b => b ? add(a + b) : a; 
console.log(add(1)(2)(3)(4)());


1

यहाँ आप C # में करी कार्यान्वयन का सरल विवरण पा सकते हैं। टिप्पणियों में, मैंने यह दिखाने की कोशिश की है कि करी कैसे उपयोगी हो सकती है:

public static class FuncExtensions {
    public static Func<T1, Func<T2, TResult>> Curry<T1, T2, TResult>(this Func<T1, T2, TResult> func)
    {
        return x1 => x2 => func(x1, x2);
    }
}

//Usage
var add = new Func<int, int, int>((x, y) => x + y).Curry();
var func = add(1);

//Obtaining the next parameter here, calling later the func with next parameter.
//Or you can prepare some base calculations at the previous step and then
//use the result of those calculations when calling the func multiple times 
//with different input parameters.

int result = func(1);

1

करीना जावा स्क्रिप्ट के उच्च-क्रम के कार्यों में से एक है।

करी कई तर्कों का एक फ़ंक्शन है जिसे फिर से लिखा जाता है जैसे कि यह पहला तर्क लेता है और एक फ़ंक्शन वापस करता है जो बदले में शेष तर्कों का उपयोग करता है और मान लौटाता है।

उलझन में?

एक उदाहरण देखते हैं,

function add(a,b)
    {
        return a+b;
    }
add(5,6);

यह निम्नलिखित करी फ़ंक्शन के समान है,

function add(a)
    {
        return function(b){
            return a+b;
        }
    }
var curryAdd = add(5);
curryAdd(6);

तो इस कोड का क्या मतलब है?

अब फिर से परिभाषा पढ़ें,

करी कई तर्कों का एक फ़ंक्शन है जिसे फिर से लिखा जाता है जैसे कि यह पहला तर्क लेता है और एक फ़ंक्शन वापस करता है जो बदले में शेष तर्कों का उपयोग करता है और मान लौटाता है।

अभी भी उलझन में? मुझे गहरे में समझाएं!

जब आप इस फ़ंक्शन को कॉल करते हैं,

var curryAdd = add(5);

यह आपको इस तरह से एक फ़ंक्शन लौटाएगा,

curryAdd=function(y){return 5+y;}

तो, इसे उच्च-क्रम फ़ंक्शन कहा जाता है। मतलब, किसी फ़ंक्शन को किसी अन्य फ़ंक्शन में शामिल करना, उच्च-क्रम फ़ंक्शन के लिए एक सटीक परिभाषा है। यह किंवदंती, जावा स्क्रिप्ट के लिए सबसे बड़ा लाभ है। तो वापस आते हैं,

यह लाइन करी तर्क फ़ंक्शन के लिए दूसरा तर्क देगी।

curryAdd(6);

जो परिणाम में बदल जाता है,

curryAdd=function(6){return 5+6;}
// Which results in 11

आशा है कि आप यहाँ पर करीने के उपयोग को समझेंगे। तो, फायदे के लिए आ रहा है,

क्यों करी?

यह कोड पुन: प्रयोज्य का उपयोग करता है। कम कोड, कम त्रुटि। आप पूछ सकते हैं कि यह कम कोड कैसे है?

मैं इसे ECMA स्क्रिप्ट 6 नए फीचर एरो फ़ंक्शंस के साथ साबित कर सकता हूं।

हाँ! ECMA 6, हमें एरो फ़ंक्शंस नामक अद्भुत सुविधा प्रदान करता है,

function add(a)
    {
        return function(b){
            return a+b;
        }
    }

तीर फ़ंक्शन की सहायता से, हम उपरोक्त फ़ंक्शन को निम्नानुसार लिख सकते हैं,

x=>y=>x+y

बिल्कुल सटीक?

तो, कम कोड और कम कीड़े !!

इन उच्च-क्रम फ़ंक्शन की सहायता से कोई आसानी से बग-मुक्त कोड विकसित कर सकता है।

मैं तुम्हें चुनौती देता हूँ!

आशा है, आप समझ गए होंगे कि करी क्या है। यदि आपको किसी स्पष्टीकरण की आवश्यकता है तो कृपया यहां टिप्पणी करने के लिए स्वतंत्र महसूस करें।

शुक्रिया आपका दिन शुभ हो!


0

"रीज़निंग में रीज़निंग" का एक उदाहरण है।

let run = () => {
    Js.log("Curryed function: ");
    let sum = (x, y) => x + y;
    Printf.printf("sum(2, 3) : %d\n", sum(2, 3));
    let per2 = sum(2);
    Printf.printf("per2(3) : %d\n", per2(3));
  };
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.