क्या ग्रूवी आंशिक अनुप्रयोग को 'करी' कहते हैं?


15

ग्रूवी की एक अवधारणा है कि इसे 'करी' कहते हैं। यहाँ एक उदाहरण उनके विकि से है:

def divide = { a, b -> a / b }

def halver = divide.rcurry(2)

assert halver(8) == 4

यहाँ क्या हो रहा है, इसके बारे में मेरी समझ यह है कि दाहिने हाथ का तर्क divideमूल्य के लिए बाध्य किया जा रहा है। यह आंशिक अनुप्रयोग के एक रूप की तरह लगता है।

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

curry :: ((a, b) -> c) -> (a -> (b -> c))

उन लोगों के लिए जिन्होंने हास्केल का उपयोग नहीं किया है a, bऔर cसभी सामान्य पैरामीटर हैं। curryदो तर्कों के साथ एक फ़ंक्शन लेता है, और एक फ़ंक्शन लेता है aऔर से एक फ़ंक्शन को वापस करता bहै c। मैंने इसे और अधिक स्पष्ट करने के लिए ब्रैकेट की एक अतिरिक्त जोड़ी टाइप की है।

क्या मुझे गलत समझा गया है कि ग्रूवी उदाहरण में क्या हो रहा है या क्या यह केवल आंशिक अनुप्रयोग का नाम है? या यह वास्तव में दोनों करता है: यह कहना है कि divideएक करी फ़ंक्शन में परिवर्तित करें और फिर आंशिक रूप 2से इस नए फ़ंक्शन पर लागू करें।


1
उन लोगों के लिए जो हैस्केल msmvps.com/blogs/jon_skeet/archive/2012/01/30/…
jk

जवाबों:


14

ग्रूवी का कार्यान्वयन curryवास्तव में किसी भी बिंदु पर करी नहीं जाता है, यहां तक ​​कि पर्दे के पीछे भी। यह अनिवार्य रूप से आंशिक अनुप्रयोग के समान है।

curry, rcurryऔर ncurryतरीकों एक वापसी CurriedClosureवस्तु है कि बाध्य तर्क रखती है। इसकी एक विधि भी है getUncurriedArguments(गलत-आप करी कार्य, न कि तर्कों) जो कि उस पर दिए गए तर्कों की रचना को बाध्य तर्कों के साथ लौटाता है।

जब कोई कॉल बंद हो जाता है, तो यह अंततः की invokeMethodविधि कोMetaClassImpl कॉल करता है , जो स्पष्ट रूप से यह देखने के लिए जांचता है कि क्या कॉलिंग ऑब्जेक्ट का एक उदाहरण है CurriedClosure। यदि ऐसा है, तो यह getUncurriedArgumentsलागू करने के लिए तर्कों की पूरी सरणी की रचना करने के लिए उपर्युक्त का उपयोग करता है :

if (objectClass == CurriedClosure.class) {
    // ...
    final Object[] curriedArguments = cc.getUncurriedArguments(arguments);
    // [Ed: Yes, you read that right, curried = uncurried. :) ]
    // ...
    return ownerMetaClass.invokeMethod(owner, methodName, curriedArguments);
}

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

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

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

def add = { x, y -> x + y }
def addCurried = add.curry()   // should work like { x -> { y -> x + y } }
def add1 = addCurried(1)       // should work like { y -> 1 + y }
assert add1(1) == 2 

... और यह काम करेगा, क्योंकि addCurriedकाम करना चाहिए { x -> { y -> x + y } }। इसके बजाय यह एक रनटाइम अपवाद फेंकता है और आप थोड़ा अंदर मर जाते हैं।


1
मुझे लगता है कि तर्कों के साथ कार्यों पर आरकुर्री और एनक्र्री> 2 प्रदर्शित करता है कि यह वास्तव में सिर्फ आंशिक अनुप्रयोग है जो करी नहीं है

@jk वास्तव में, यह तर्कों के साथ कार्य पर == 2 है, जैसा कि मैं अंत में ध्यान देता हूं। :)
जॉर्डन ग्रे

3
@matcauthon कड़ाई से बोलते हुए, करीने का "उद्देश्य" एक फ़ंक्शन को कई तर्कों के साथ प्रत्येक तर्क के साथ फ़ंक्शन के नेस्टेड श्रृंखला में बदलना है। मुझे लगता है कि आप जो पूछ रहे हैं, वह एक व्यावहारिक कारण है जिसे आप करी का उपयोग करना चाहते हैं , जो कि ग्रूवी में एलआईएसपी या हास्केल की तुलना में औचित्य के लिए थोड़ा कठिन है। मुद्दा यह है कि, जो आप ज्यादातर समय का उपयोग करना चाहते हैं वह आंशिक अनुप्रयोग है, न कि करी।
जॉर्डन ग्रे

4
+1 के लिएand you die a little inside
थॉमस एडिंग

1
वाह, मैं आपके उत्तर को पढ़ने के बाद करीना को बेहतर समझता हूं: +1 और धन्यवाद! प्रश्न के लिए विशिष्ट, मुझे यह पसंद है कि आपने कहा, "आंशिक अनुप्रयोग के साथ करीने से भरा हुआ।"
ग्लेनपेटर्सन

3

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

f :: (a,b,c) -> d

इसका क्यूट फॉर्म होगा

fcurried :: a -> b -> c -> d

हालांकि ग्रूवी की करी के बराबर कुछ वापस आ जाएगा (1 तर्क एक्स के साथ कहा जाता है)

fgroovy :: (b,c) -> d 

जो निश्चित x के मान के साथ f को कॉल करेगा

यानी जबकि ग्रूवी की करी एन -1 तर्कों के साथ फ़ंक्शंस लौटा सकती है, ठीक से करी गई फ़ंक्शंस में केवल 1 तर्क होता है, इसलिए ग्रूवी करी के साथ करी नहीं जा सकता है


2

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

http://groovy.markmail.org/thread/c4ycxdzm3ack6xxb

मौजूदा कार्यप्रणाली किसी न किसी रूप में बनी रहेगी और पीछे की अनुकूलता को ध्यान में रखा जाएगा जब नए तरीकों को नाम देने के लिए कॉल किया जाएगा आदि - इसलिए मैं इस स्तर पर यह नहीं कह सकता कि नए / पुराने तरीकों का अंतिम नामकरण क्या है। हो। शायद नामकरण पर एक समझौता है लेकिन हम देखेंगे।

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


1

आईबीएम में पाए गए इस विभेदीकरण को देखते हुए:

करी शब्द हास्केल करी से लिया गया है, जो गणितज्ञ हैं जिन्होंने आंशिक कार्यों की अवधारणा विकसित की है। करीने से तात्पर्य कई तर्कों को लेने से है जो कई तर्कों को लेते हैं, जिसके परिणामस्वरूप एक नया कार्य होता है जो शेष तर्कों को लेता है और परिणाम देता है।

halverआपका नया (करी) फ़ंक्शन (या बंद) है, जो अब सिर्फ एक पैरामीटर लेता है। कॉलिंग halver(10)5 में परिणाम होगा।

वहाँ यह एक फ़ंक्शन को n-1 तर्कों के साथ एक फ़ंक्शन में n तर्कों के साथ बदल देता है। आपके हैकेल उदाहरण द्वारा वही कहा जाता है जो करी करता है।


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

1
विकिपीडिया की परिभाषा में आईबीएम से समान है: गणित और कंप्यूटर विज्ञान में, करीकरण एक फ़ंक्शन को बदलने की तकनीक है जो कई तर्कों (या तर्कों का एक nuple) को इस तरह से लेती है कि इसे एक के रूप में कहा जा सकता है एकल तर्क (आंशिक अनुप्रयोग) के साथ प्रत्येक कार्य की श्रृंखला। Groovy एक फ़ंक्शन (दो तर्कों के साथ) को rcurryफ़ंक्शन (जो एक तर्क लेता है) को फ़ंक्शन में (अब केवल एक तर्क के साथ) रूपांतरित करता है। मैंने अपने परिणामी फ़ंक्शन को प्राप्त करने के लिए अपने बेस फ़ंक्शन के तर्क के साथ करी फ़ंक्शन को जंजीर किया।
Matcauthon

3
नहीं, विकिपीडिया की परिभाषा अलग है - आंशिक अनुप्रयोग तब होता है जब आप करी फ़ंक्शन को कॉल करते हैं - न कि जब आप इसे परिभाषित करते हैं जो कि ग्रूवी करता है
jk।

6
@ जक सही है। विकिपीडिया स्पष्टीकरण को फिर से पढ़ें और आप देखेंगे कि जो वापस मिलता है वह एक तर्क के साथ कार्यों की एक श्रृंखला है, न कि n - 1तर्कों के साथ एक फ़ंक्शन । मेरे उत्तर के अंत में उदाहरण देखें; यह भी देखें कि लेख में बाद में किए जा रहे भेद के बारे में अधिक जानकारी के लिए। en.wikipedia.org/wiki/…
जोर्डन ग्रे

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