करी और आंशिक अनुप्रयोग के बीच क्या अंतर है?


438

मैं अक्सर इंटरनेट पर विभिन्न शिकायतों को देखता हूं कि करी के अन्य लोगों के उदाहरण करी नहीं हैं, लेकिन वास्तव में सिर्फ आंशिक अनुप्रयोग हैं।

मुझे आंशिक विवरण नहीं मिला है कि आंशिक अनुप्रयोग क्या है, या यह करी से कैसे भिन्न होता है। ऐसा प्रतीत होता है कि एक सामान्य भ्रम है, कुछ स्थानों पर करी के रूप में वर्णित समान उदाहरणों के साथ, और दूसरों में आंशिक अनुप्रयोग।

क्या कोई मुझे दोनों शब्दों की परिभाषा प्रदान कर सकता है, और वे कैसे भिन्न हैं इसका विवरण?

जवाबों:


256

Currying की एक एकल समारोह परिवर्तित n में तर्क n एक भी तर्क से प्रत्येक के साथ काम करता है। निम्नलिखित कार्य को देखते हुए:

function f(x,y,z) { z(x(y));}

जब करी, बन जाती है:

function f(x) { lambda(y) { lambda(z) { z(x(y)); } } }

च (x, y, z) का पूरा आवेदन प्राप्त करने के लिए, आपको यह करने की आवश्यकता है:

f(x)(y)(z);

कई कार्यात्मक भाषाएं आपको लिखने देती हैं f x y z। यदि आप केवल कॉल f x yया एफ (x) (y) करते हैं, तो आपको आंशिक रूप से लागू फ़ंक्शन मिलता है- रिटर्न वैल्यू lambda(z){z(x(y))}x और y के वैल्यू-इन वैल्यूज़ के साथ बंद होता है f(x,y)

आंशिक अनुप्रयोग का उपयोग करने का एक तरीका यह है कि कार्यों को सामान्यीकृत कार्यों के आंशिक अनुप्रयोगों के रूप में परिभाषित किया जाए, जैसे कि गुना :

function fold(combineFunction, accumulator, list) {/* ... */}
function sum     = curry(fold)(lambda(accum,e){e+accum}))(0);
function length  = curry(fold)(lambda(accum,_){1+accum})(empty-list);
function reverse = curry(fold)(lambda(accum,e){concat(e,accum)})(empty-list);

/* ... */
@list = [1, 2, 3, 4]
sum(list) //returns 10
@f = fold(lambda(accum,e){e+accum}) //f = lambda(accumulator,list) {/*...*/}
f(0,list) //returns 10
@g = f(0) //same as sum
g(list)  //returns 10

40
आप कह रहे हैं कि आंशिक अनुप्रयोग तब होता है जब आप किसी फ़ंक्शन की करी करते हैं, और कुछ का उपयोग करते हैं, लेकिन सभी परिणामी कार्यों के नहीं?
स्पूनमाइजर

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

1
एक फ़ंक्शन च (ए, बी, सी, डी) को जी (ए, बी) में बदलकर आंशिक अनुप्रयोग के रूप में गिना जाएगा? या यह केवल तब होता है जब करी कार्यों में लगाया जाता है? एक दर्द होने के लिए क्षमा करें, लेकिन मैं यहाँ एक स्पष्ट जवाब के लिए परेशान हूँ।
स्पूनमाइज़र

2
@ मर्क: मुझे लगता है कि यह उन अवधारणाओं में से एक है जो मेरे अंदर की पांडित्य को बाहर लाती है - लेकिन आधिकारिक सूत्रों से एक अपील बहुत कम संतुष्ट करती है, क्योंकि वे सभी एक दूसरे की ओर इशारा करती हैं। विकिपीडिया शायद ही ऐसा हो जिसे मैं आधिकारिक स्रोत मानता हूँ, लेकिन मैं समझता हूँ कि इसे और खोजना मुश्किल है। यह कहने के लिए पर्याप्त है कि मुझे लगता है कि हम दोनों जानते हैं कि हम जो भी बोलते हैं और शक्ति है, भले ही हम वर्नाक्यूलर के विवरणों पर सहमत या असहमत हों या नहीं! :) धन्यवाद मार्क!
जेसन बंटिंग

5
@JasonBunting, आपकी पहली टिप्पणी के बारे में, आप जिस बारे में बात कर रहे थे वह घट रही है । करी इनपुट के रूप में एक मल्टी-आर्ग फंक्शन ले रहा है और आउटपुट के रूप में 1-आर्ग फंक्शन्स की श्रंखला लौटा रहा है। De-curry इनपुट के रूप में 1-arg फ़ंक्शन की एक श्रृंखला ले रही है और आउटपुट के रूप में एक बहु-arg फ़ंक्शन लौटा रही है। जैसा कि stackoverflow.com/a/23438430/632951
पेसियर

165

यह देखने का सबसे आसान तरीका है कि वे कैसे अलग हैं, एक वास्तविक उदाहरण पर विचार करें । मान लेते हैं कि हमारे पास एक फ़ंक्शन है Addजो इनपुट के रूप में 2 नंबर लेता है और आउटपुट के रूप में एक नंबर देता है, उदाहरण के लिए Add(7, 5)रिटर्न 12। इस मामले में:

  • Addमान के साथ फ़ंक्शन को लागू करने वाला आंशिक7 हमें आउटपुट के रूप में एक नया फ़ंक्शन देगा। वह फ़ंक्शन स्वयं इनपुट के रूप में 1 नंबर लेता है और एक नंबर आउटपुट करता है। जैसे की:

    Partial(Add, 7); // returns a function f2 as output
    
                     // f2 takes 1 number as input and returns a number as output
    

    तो हम यह कर सकते हैं:

    f2 = Partial(Add, 7);
    f2(5); // returns 12;
           // f2(7)(5) is just a syntactic shortcut
    
  • फ़ंक्शन Addको करीने से हमें आउटपुट के रूप में एक नया फ़ंक्शन मिलेगा। यही कारण है कि समारोह में ही इनपुट और आउटपुट के रूप में 1 नंबर लेता है अभी तक एक और नया कार्य करते हैं। वह तीसरा फ़ंक्शन इनपुट के रूप में 1 नंबर लेता है और आउटपुट के रूप में एक नंबर देता है। जैसे की:

    Curry(Add); // returns a function f2 as output
    
                // f2 takes 1 number as input and returns a function f3 as output
                // i.e. f2(number) = f3
    
                // f3 takes 1 number as input and returns a number as output
                // i.e. f3(number) = number
    

    तो हम यह कर सकते हैं:

    f2 = Curry(Add);
    f3 = f2(7);
    f3(5); // returns 12
    

दूसरे शब्दों में, "करी" और "आंशिक अनुप्रयोग" दो पूरी तरह से अलग कार्य हैं। करीने में ठीक 1 इनपुट लगता है, जबकि आंशिक अनुप्रयोग में 2 (या अधिक) इनपुट होते हैं।

भले ही वे दोनों एक फ़ंक्शन को आउटपुट के रूप में लौटाते हैं, लेकिन दिए गए फ़ंक्शन ऊपर दिखाए गए अनुसार पूरी तरह से भिन्न रूप हैं।


24
आंशिक अनुप्रयोग एक फ़ंक्शन n-aryको (x - n)-ary, से n-aryकरने के लिए करीने में बदल देता है n * 1-ary। एक आंशिक रूप से लागू फ़ंक्शन में एक कम गुंजाइश (आवेदन की) है, अर्थात, Add7की तुलना में कम अभिव्यंजक है Add। दूसरी तरफ एक क्युरेटेड फंक्शन मूल फंक्शन की तरह एक्सप्रेसिव होता है।
बॉब

4
मेरा मानना ​​है कि अधिक विशिष्ट गुण तब होता है जब हम f (x, y, z) => R पर क्लिक करते हैं, हमें f (x) मिलता है, जो g (y) => h (z) => R देता है, प्रत्येक एक एकल तर्क का उपभोग करता है; लेकिन जब हम आंशिक रूप से f (x, y, z) को f (x) के रूप में लागू करते हैं तो हमें g (y, z) => R, यानी दो तर्क मिलते हैं। यदि उस विशेषता के लिए नहीं, तो हम कह सकते हैं कि करीना 0 तर्कों के लिए आंशिक अनुप्रयोग की तरह है, इस प्रकार सभी तर्कों को छोड़ दिया जाता है; हालाँकि वास्तविकता में (0) आंशिक रूप से 0 तर्कों पर लागू किया जाता है, एक फ़ंक्शन है जिसका उपभोग एक बार में 3 कग होता है, विपरीत f () के विपरीत।
मक्सिम गुमेरोव

2
एक बार फिर से सही उत्तर पहले या सबसे अधिक मत वाले नहीं हैं: इस उत्तर के अंत में करी बनाम आंशिक के हस्ताक्षर की सरल व्याख्या वास्तव में प्रश्न को हल करने का सबसे आसान तरीका है।
fnl

2
टिप्पणी का क्या f2(7)(5) is just a syntactic shortcutअर्थ है? (मुझे बहुत कम पता है।) f2पहले से ही शामिल नहीं है / "7 के बारे में जानते हैं?"
Zach Mierzejewski

@ स्पेसियर, curryक्या कहीं पर एक कार्यान्वयन है (ऐसा मत सोचो कि यह functools)
अलंकाल्वीति

51

नोट: यह F # मूल बातें से लिया गया था। .NET डेवलपर्स के लिए एक उत्कृष्ट परिचयात्मक लेख है।

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

let multiply x y = x * y    
let double = multiply 2
let ten = double 5

ठीक उसी समय, आपको व्यवहार को देखना चाहिए जो अधिकांश अनिवार्य भाषाओं से अलग है। दूसरा कथन एक नए फ़ंक्शन को बनाता है जिसे एक फ़ंक्शन को एक तर्क पास करके दोहराता है जो दो लेता है। परिणाम एक ऐसा फ़ंक्शन है जो एक अंतर तर्क को स्वीकार करता है और समान आउटपुट देता है जैसे कि आपने x को 2 के बराबर गुणा किया था और उस तर्क के बराबर y। व्यवहार के संदर्भ में, यह इस कोड के समान है:

let double2 z = multiply 2 z

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

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

डबल बनाने के लिए, मल्टीपल फ़ंक्शंस की श्रृंखला में पहले फ़ंक्शन का मूल्यांकन आंशिक रूप से लागू करने के लिए किया जाता है। परिणामी फ़ंक्शन को नाम डबल दिया गया है। जब दोहरे का मूल्यांकन किया जाता है, तो यह परिणाम बनाने के लिए आंशिक रूप से लागू मूल्य के साथ अपने तर्क का उपयोग करता है।


33

दिलचस्प सवाल। थोड़ी खोज करने के बाद, "आंशिक कार्य अनुप्रयोग में सुधार नहीं हो रहा है" मैंने जो सबसे अच्छा स्पष्टीकरण दिया, वह मिला। मैं यह नहीं कह सकता कि व्यावहारिक अंतर मेरे लिए विशेष रूप से स्पष्ट है, लेकिन फिर मैं एफपी विशेषज्ञ नहीं हूं ...

एक अन्य उपयोगी-दिखने वाला पृष्ठ (जो मैं मानता हूं कि मैंने अभी तक पूरी तरह से पढ़ा नहीं है) "जावा क्लोज़र के साथ करी और आंशिक अनुप्रयोग" है

ऐसा लगता है कि यह व्यापक रूप से भ्रमित करने वाली जोड़ी है, आपको बुरा लगता है।


5
पहला लिंक अंतर के बारे में स्पॉट-ऑन है। यहाँ एक और उपयोगी है जो मैंने पाया: bit.ly/CurryingVersusPartialApplication
जेसन बंटिंग

5
करी करना ट्यूपल्स के साथ करना है (एक फ़ंक्शन को चालू करना जो एक ट्यूपल तर्क को एक में ले जाता है जो एन अलग-अलग तर्क लेता है, और इसके विपरीत)। आंशिक आवेदन कुछ तर्कों के लिए एक फ़ंक्शन लागू करने की क्षमता है, शेष तर्कों के लिए एक नया फ़ंक्शन उपज। यह याद रखना आसान है कि क्या आप सिर्फ टेढ़ी खीर करने के लिए == सोचते हैं।
डॉन स्टीवर्ट

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


11
विश्वास नहीं हो सकता है कि आपको एक युगल लिंक के लिए 20 अपवोट मिले और एक प्रवेश जिसे आप वास्तव में करी और आंशिक आवेदन के बीच का अंतर नहीं जानते हैं। अच्छा खेला, सर।
एलियनवेबजी

16

मैंने इसका जवाब एक और सूत्र https://stackoverflow.com/a/12846865/1685865 में दिया है । संक्षेप में, आंशिक फ़ंक्शन अनुप्रयोग कम तर्कों के साथ किसी अन्य फ़ंक्शन का उत्पादन करने के लिए दिए गए बहु-चलन फ़ंक्शन के कुछ तर्कों को ठीक करने के बारे में है, जबकि करी एक एन फ़ंक्शन के फ़ंक्शन को एक यूनेरी फ़ंक्शन में बदलने के बारे में है जो एक अनियंत्रित फ़ंक्शन देता है ... एक उदाहरण इस पोस्ट के अंत में करी को दिखाया गया है।]

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

(करी का उदाहरण)

व्यवहार में कोई सिर्फ लिखना नहीं होगा

lambda x: lambda y: lambda z: x + y + z

या समकक्ष जावास्क्रिप्ट

function (x) { return function (y){ return function (z){ return x + y + z }}}

के बजाय

lambda x, y, z: x + y + z

करी के लिए।


1
क्या आप कहेंगे कि करीना आंशिक आवेदन का एक विशिष्ट मामला है?
स्पूनमाइजर

1
@SpoonMeiser, नहीं, करीकरण आंशिक अनुप्रयोग का एक विशिष्ट मामला नहीं है: 2-इनपुट फ़ंक्शन का एक आंशिक अनुप्रयोग फ़ंक्शन को करीने के समान नहीं है। Stackoverflow.com/a/23438430/632951 देखें ।
पचेरियर

10

करी एक तर्क का एक फ़ंक्शन है जो एक फ़ंक्शन लेता है fऔर एक नया फ़ंक्शन देता है h। ध्यान दें कि hएक तर्क लेता है Xऔर एक फ़ंक्शन देता है जो नक्शे में आता Yहै Z:

curry(f) = h 
f: (X x Y) -> Z 
h: X -> (Y -> Z)

आंशिक अनुप्रयोग दो (या अधिक) तर्कों का एक फ़ंक्शन है जो एक फ़ंक्शन लेता fहै fऔर एक नया फ़ंक्शन देता है और एक या अधिक अतिरिक्त तर्क देता है g:

part(f, 2) = g
f: (X x Y) -> Z 
g: Y -> Z

भ्रम पैदा होता है क्योंकि दो-तर्क फ़ंक्शन के साथ निम्नलिखित समानता रखती है:

partial(f, a) = curry(f)(a)

दोनों पक्ष समान-तर्क फ़ंक्शन का उत्पादन करेंगे।

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

अंतर व्यवहार में भी है, जबकि करी पूरे मूल फ़ंक्शन को पुनरावर्ती रूप से (प्रत्येक तर्क के लिए एक बार) बदल देती है, आंशिक आवेदन केवल एक कदम प्रतिस्थापन है।

स्रोत: विकिपीडिया Currying


8

जावास्क्रिप्ट और आंशिक अनुप्रयोग के बीच का अंतर इस जावास्क्रिप्ट उदाहरण के माध्यम से सबसे अच्छा समझा जा सकता है:

function f(x, y, z) {
    return x + y + z;
}

var partial = f.bind(null, 1);

6 === partial(2, 3);

आंशिक आवेदन का परिणाम छोटे धमनी के एक समारोह में होता है; ऊपर के उदाहरण में, f3 की एक अरेटी है, जबकि partialकेवल 2 की एक अरेटी है। इससे भी महत्वपूर्ण बात, आंशिक रूप से लागू फ़ंक्शन परिणाम को लागू करने के तुरंत बाद लौटा देगा , न कि एक और फ़ंक्शन करी चेन के नीचे। इसलिए यदि आप ऐसा कुछ देख रहे हैं partial(2)(3), तो यह वास्तविकता में आंशिक अनुप्रयोग नहीं है।

आगे की पढाई:


"आंशिक रूप से लागू किया गया फ़ंक्शन, आह्वान किए जाने के तुरंत बाद परिणाम लौटाएगा" - यह सही नहीं है, है? जब मैं आंशिक रूप से एक फ़ंक्शन लागू करता हूं, तो वह अभिव्यक्ति एक फ़ंक्शन देता है, न कि "एक परिणाम"। ठीक है, आप शायद इसका मतलब यह है कि इस बाद के समारोह, जब शेष तर्कों के साथ बुलाया जाता है, तो परिणाम को लौटाता है, एक कदम नीचे खुदाई के विपरीत। लेकिन कोई भी वास्तव में नहीं कहता है कि आपको सभी शेष तर्क निर्दिष्ट करने होंगे: आप आंशिक आवेदन के परिणाम को आंशिक रूप से लागू कर सकते हैं, और वह एक बार फिर एक फ़ंक्शन होगा, "परिणाम" नहीं
मक्सिम गुमेरोव

6

सरल उत्तर

करी: आपको एक फ़ंक्शन को कॉल करने देता है, इसे कई कॉल में विभाजित करता है, प्रति तर्क एक कॉल प्रदान करता है।

आंशिक: आपको फ़ंक्शन को कॉल करने देता है, कई कॉल में विभाजित करता है, प्रति कॉल कई तर्क प्रदान करता है।


सरल संकेत

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

वास्तविक अंतर तब देखा जा सकता है जब फ़ंक्शन में 2 से अधिक तर्क हों।


सरल ई (सी) (नमूना)

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

function process(context, success_callback, error_callback, subject) {...}

हमेशा संदर्भ और कॉलबैक जैसे तर्कों को पारित करना, अगर वे हमेशा समान रहेंगे? फ़ंक्शन के लिए बस कुछ मानों को बांधें

processSubject = _.partial(process, my_context, my_success, my_error)

और पर इसे कहते subject1 और foobar साथ

processSubject('subject1');
processSubject('foobar');

आराम, यह नहीं है? 😉

साथ currying आप समय के अनुसार एक तर्क पारित करने के लिए आवश्यकता होगी

curriedProcess = _.curry(process);
processWithBoundedContext = curriedProcess(my_context);
processWithCallbacks = processWithBoundedContext(my_success)(my_error); // note: these are two sequential calls

result1 = processWithCallbacks('subject1');
// same as: process(my_context, my_success, my_error, 'subject1');
result2 = processWithCallbacks('foobar'); 
// same as: process(my_context, my_success, my_error, 'foobar');

अस्वीकरण

मैंने सभी शैक्षणिक / गणितीय स्पष्टीकरण को छोड़ दिया। क्योंकि मैं यह नहीं जानता। शायद इससे 🙃 को मदद मिले


4

सीखने के दौरान मेरे पास यह सवाल बहुत था और तब से इसे कई बार पूछा जा चुका है। सबसे आसान तरीका मैं अंतर का वर्णन कर सकता हूं कि दोनों एक ही हैं :) मुझे समझाने दें ... स्पष्ट रूप से अंतर हैं।

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

add = (x, y) => x + y

अगर मुझे "addOne" फंक्शन चाहिए, तो मैं इसे आंशिक रूप से लागू कर सकता हूं या इसे कर सकता हूं:

addOneC = curry(add, 1)
addOneP = partial(add, 1)

अब उनका उपयोग करना स्पष्ट है:

addOneC(2) #=> 3
addOneP(2) #=> 3

तो क्या अंतर है? ठीक है, यह सूक्ष्म है, लेकिन आंशिक आवेदन में कुछ तर्कों की आपूर्ति करना शामिल है और लौटाया गया फ़ंक्शन फिर अगले आह्वान पर मुख्य कार्य को अंजाम देगा, जबकि करी तब तक इंतजार करता रहेगा जब तक कि सभी तर्क आवश्यक न हों:

curriedAdd = curry(add) # notice, no args are provided
addOne = curriedAdd(1) # returns a function that can be used to provide the last argument
addOne(2) #=> returns 3, as we want

partialAdd = partial(add) # no args provided, but this still returns a function
addOne = partialAdd(1) # oops! can only use a partially applied function once, so now we're trying to add one to an undefined value (no second argument), and we get an error

संक्षेप में, कुछ मूल्यों को प्रीफ़िल करने के लिए आंशिक अनुप्रयोग का उपयोग करें, यह जानते हुए कि अगली बार जब आप विधि को कॉल करते हैं, तो यह निष्पादित करेगा, सभी अपरिष्कृत तर्कों को अपरिभाषित छोड़ देगा; जब आप फ़ंक्शन हस्ताक्षर को पूरा करने के लिए आवश्यक रूप से आंशिक रूप से लागू फ़ंक्शन को लगातार वापस करना चाहते हैं तो करीने का उपयोग करें। एक अंतिम वंचित उदाहरण:

curriedAdd = curry(add)
curriedAdd()()()()()(1)(2) # ugly and dumb, but it works

partialAdd = partial(add)
partialAdd()()()()()(1)(2) # second invocation of those 7 calls fires it off with undefined parameters

उम्मीद है की यह मदद करेगा!

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


3

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

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


3

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

# partial application
partial_apply = (func) ->
  args = [].slice.call arguments, 1
  -> func.apply null, args.concat [].slice.call arguments

sum_variadic = -> [].reduce.call arguments, (acc, num) -> acc + num

add_to_7_and_5 = partial_apply sum_variadic, 7, 5

add_to_7_and_5 10 # returns 22
add_to_7_and_5 10, 11, 12 # returns 45

# currying
curry = (func) ->
  num_args = func.length
  helper = (prev) ->
    ->
      args = prev.concat [].slice.call arguments
      return if args.length < num_args then helper args else func.apply null, args
  helper []

sum_of_three = (x, y, z) -> x + y + z
curried_sum_of_three = curry sum_of_three
curried_sum_of_three 4 # returns a function expecting more arguments
curried_sum_of_three(4)(5) # still returns a function expecting more arguments
curried_sum_of_three(4)(5)(6) # returns 15
curried_sum_of_three 4, 5, 6 # returns 15

यह स्पष्ट रूप से एक विरोधाभासी उदाहरण है, लेकिन ध्यान दें कि किसी भी संख्या के तर्कों को आंशिक रूप से लागू करने वाला फ़ंक्शन हमें किसी फ़ंक्शन को निष्पादित करने की अनुमति देता है, लेकिन कुछ प्रारंभिक डेटा के साथ। एक फ़ंक्शन को करी करना समान है लेकिन हमें टुकड़ों में N- पैरामीटर फ़ंक्शन को निष्पादित करने की अनुमति देता है, लेकिन केवल तब तक, जब तक सभी एन मापदंडों के लिए जिम्मेदार नहीं हैं।

फिर से, यह मेरे द्वारा पढ़ी गई चीजों से लिया गया है। यदि कोई असहमत है, तो मैं एक टिप्पणी की सराहना करूंगा कि तत्काल पतन के बजाय क्यों। इसके अलावा, यदि कॉफीस्क्रिप्ट पढ़ना मुश्किल है, तो कृपया coffeescript.org पर जाएं, "कोशिश करें" कॉफ़ीस्क्रिप्ट पर क्लिक करें और संकलित संस्करण को देखने के लिए अपने कोड में पेस्ट करें, जो (उम्मीद) अधिक समझ में आ सकता है। धन्यवाद!


2

मैं उन अधिकांश लोगों को मानने जा रहा हूं जो यह प्रश्न पूछते हैं कि वे पहले से ही मूल अवधारणाओं से परिचित हैं, इसलिए उनके बारे में बात करने की कोई आवश्यकता नहीं है। यह ओवरलैप है जो भ्रामक हिस्सा है।

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

हर एक को परिभाषित करने के बजाय, उनके अंतरों को उजागर करना आसान है - सीमा।

करी तब होती है जब आप फ़ंक्शन को परिभाषित करते हैं।

आंशिक अनुप्रयोग तब होता है जब आप फ़ंक्शन को कॉल करते हैं।

आवेदन एक समारोह को बुलाने के लिए गणित-बात है।

आंशिक अनुप्रयोग के लिए क्यूरेड फ़ंक्शन को कॉल करने और रिटर्न प्रकार के रूप में फ़ंक्शन प्राप्त करने की आवश्यकता होती है।


1

यहाँ अन्य शानदार उत्तर हैं, लेकिन मेरा मानना ​​है कि जावा में यह उदाहरण (मेरी समझ के अनुसार) कुछ लोगों के लिए लाभकारी हो सकता है:

public static <A,B,X> Function< B, X > partiallyApply( BiFunction< A, B, X > aBiFunction, A aValue ){
    return b -> aBiFunction.apply( aValue, b );
}

public static <A,X> Supplier< X > partiallyApply( Function< A, X > aFunction, A aValue ){
    return () -> aFunction.apply( aValue );
}

public static <A,B,X> Function<  A, Function< B, X >  > curry( BiFunction< A, B, X > bif ){
    return a -> partiallyApply( bif, a );
}

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

यदि आप कॉपी और पेस्ट करना चाहते हैं, तो निम्न प्रकार से काम करने के लिए निम्नलिखित noisier है, लेकिन मित्र के रूप में अधिक उदार हैं:

public static <A,B,X> Function< ? super B, ? extends X > partiallyApply( final BiFunction< ? super A, ? super B, X > aBiFunction, final A aValue ){
    return b -> aBiFunction.apply( aValue, b );
}

public static <A,X> Supplier< ? extends X > partiallyApply( final Function< ? super A, X > aFunction, final A aValue ){
    return () -> aFunction.apply( aValue );
}

public static <A,B,X> Function<  ? super A,  Function< ? super B, ? extends X >  > curry( final BiFunction< ? super A, ? super B, ? extends X > bif ){
    return a -> partiallyApply( bif, a );
}

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

0

इसे लिखने में, मैंने करीने और बेझिझक उलझा दिया। वे कार्यों पर उलटा रूपांतरण हैं। यह वास्तव में मायने नहीं रखता है कि आप क्या कहते हैं, जब तक आप परिवर्तन और उसके व्युत्क्रम का प्रतिनिधित्व करते हैं।

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

(+) :: Int -> Int -> Int

अब, आप इसे एक फ़ंक्शन में कैसे बदलते हैं जो एक एकल तर्क लेता है? तुम, बेशक धोखा!

plus :: (Int, Int) -> Int

ध्यान दें कि प्लस अब एक तर्क लेता है (जो दो चीजों से बना है)। उत्तम!

इसका क्या मतलब है? ठीक है, अगर आपके पास एक फ़ंक्शन है जो दो तर्क लेता है, और आपके पास कुछ तर्क हैं, तो यह जानना अच्छा है कि आप फ़ंक्शन को तर्कों पर लागू कर सकते हैं, और अभी भी वह प्राप्त कर सकते हैं जो आप अपेक्षा करते हैं। और, वास्तव में, यह करने के लिए पाइपलाइन पहले से ही मौजूद है, ताकि आपको स्पष्ट पैटर्न मिलान जैसी चीजें करने की ज़रूरत न हो। तुमको बस यह करना है:

(uncurry (+)) (1,2)

तो आंशिक फ़ंक्शन अनुप्रयोग क्या है? यह एक फ़ंक्शन को एक तर्क के साथ दो तर्कों में एक फ़ंक्शन में बदलने का एक अलग तरीका है। हालांकि यह अलग तरह से काम करता है। फिर, आइए एक उदाहरण के रूप में लेते हैं (+)। हम इसे एक ऐसे फ़ंक्शन में कैसे बदल सकते हैं जो एक एकल Int को तर्क के रूप में लेता है? हम धोखा देते हैं!

((+) 0) :: Int -> Int

वह फ़ंक्शन जो किसी भी इंट में शून्य जोड़ता है।

((+) 1) :: Int -> Int

किसी भी इंट में 1 जोड़ता है। आदि इनमें से प्रत्येक मामले में, (+) "आंशिक रूप से लागू" है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.