2012-07-21 15 views
5

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

MySum = lambda x, y : x + y; 

अब मैं जो एक ही मूल्य है कि MySum होगा रिटर्न छोटे arity के साथ एक समारोह प्राप्त करने के लिए एक पैरामीटर तय कर रहा हूँ वापसी अगर मैं (आंशिक आवेदन) एक ही मानकों के साथ यह कहा जाता है:

int MySum(int x, int y) { return x + y; } 
int MyPartialSum(int x) { return MySum(x, 0); } 

तो, डु:

MyPartialSum = lambda x : MySum(x, 0); 

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

उत्तर

3

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

दूसरे शब्दों में, आप समारोह F(a, b), a का आंशिक आवेदन लागू होने वाला B(fn, a) जहां F(a, b) = B(F, a)(b) कैसा दिखेगा एक समारोह है।

आपके उदाहरण में आप केवल मौजूदा कार्यों को आंशिक आवेदन लागू करने के बजाय नए कार्य बना रहे हैं।

def curry_first(fn, arg): 
    def foo(*args): 
     return fn(arg, *args) 
    return foo 

यह आपूर्ति समारोह और तर्क पर एक बंद बनाता है:

यहाँ अजगर में एक उदाहरण है। एक नया फ़ंक्शन वापस कर दिया जाता है जो पहले तर्क को नए तर्क हस्ताक्षर के साथ कॉल करता है। बंद करना महत्वपूर्ण है - यह fnarg तक पहुंच की अनुमति देता है।

add = lambda x, y : x + y; 
add2 = curry_first(add, 2) 
add2(4) # returns 6 

मैं आमतौर पर सुना है इस currying के रूप में भेजा: अब आप बात की इस तरह कर सकते हैं।

+0

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

+0

जो ठीक ऊपर हो रहा है। जहां तक ​​मैं कह सकता हूं, करीना सिर्फ फॉर्म की एक विशेष अभिव्यक्ति है। – Hamish

+0

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

0

मेरे लिए, आंशिक Sum का उपयोग करके, यह सुनिश्चित करता है कि आप केवल संख्याओं (MySum) को योग करने के लिए एक फ़ंक्शन पर निर्भर करते हैं और इससे चीजें गलत होने पर डीबगिंग को और अधिक आसान बना दिया जाएगा, क्योंकि आपको चिंता करने की आवश्यकता नहीं है अपने कोड के दो अलग-अलग हिस्सों में अपने कोड के तर्क के बारे में।

भविष्य में आप MySum के तर्क को बदलने का फैसला करते हैं, तो (उदाहरण के लिए कहते हैं, इसे वापस कर x + y +1) तो आप क्योंकि यह MySum

यहां तक ​​कि अगर कॉल MyPartialSum बारे में चिंता करने की ज़रूरत नहीं होगी यह बेवकूफ लगता है, इस तरह लिखा कोड कोड में निर्भरताओं की प्रक्रिया को सरल बनाना है। मुझे यकीन है कि आप बाद में अपने अध्ययन में देखेंगे।

+0

मुझे लगता है। वैसे भी मैं यह कर सकता हूं कि मैं जिस भाषा का उपयोग कर रहा हूं, वह बंद होने का समर्थन कर रहा है या नहीं। इस मामले में बंदरगाह बहुत बेकार हैं – Cancer

+0

हालांकि यह सिर्फ 'लेखन कोड' है। आंशिक आवेदन एक * समारोह * वापस नहीं करना चाहिए, न कि परिणाम। – Hamish

+0

क्या यह चाहिए? यह तो बहुत ही मज़ेदार है! तो अगर मैंने परिभाषित किया: MyPartialSum = lambda x: lambda x: MySum (x, 0) जो "सत्य" आंशिक अनुप्रयोग होगा? यह मेरे लिए बहुत स्पष्ट नहीं है – Cancer

1

आंशिक समारोह आवेदन की तरह

sum = lambda x, y: x + y 
inc = lambda x: sum(x, 1) 

सूचना है कि 'इंक' 'योग' आंशिक रूप से लागू किया है, से कुछ भी कब्जा करने के बिना, कम तर्क के साथ एक और समारोह उपज के लिए किसी दिए गए समारोह के कुछ तर्क फिक्सिंग के बारे में है संदर्भ (जैसा कि आपने बंद करने का उल्लेख किया है)।

लेकिन, ऐसे हाथ से लिखे गए (आमतौर पर अज्ञात) फ़ंक्शन बहुत ही कठिन हैं। कोई फ़ंक्शन फ़ैक्टरी का उपयोग कर सकता है, जो एक आंतरिक फ़ंक्शन देता है। भीतरी समारोह की तरह

# sum = lambda x, y: x + y 
def makePartialSumF(n): 
    def partialSumF(x): 
     return sum(x, n) 
    return partialSumF 

inc = makePartialSumF(1) 
plusTwo = makePartialSumF(2) 

यहाँ, उसके संदर्भ से कुछ चर पर कब्जा कर parameterized जा सकती है, कारखाने makePartialSumF दो बार शुरू हो जाती है। आंशिक SumF फ़ंक्शन में प्रत्येक कॉल परिणाम (विभिन्न मानों को n के रूप में कैप्चर करना)। बंद करने का उपयोग आंशिक अनुप्रयोग के कार्यान्वयन को सुविधाजनक बनाता है। तो आप कह सकते हैं आंशिक आवेदन बंद करने के माध्यम से लागू किया जा सकता है। बेशक, बंद कई अन्य चीजें कर सकते हैं! (एक तरफ नोड के रूप में, अजगर उचित बंद नहीं है।)

Currying एक एकल समारोह जो उदाहरण के लिए एक एकल समारोह ... रिटर्न में एन तर्क के एक समारोह मोड़ के बारे में है कि हम एक समारोह है जो तीन तर्क लेता है और एक मान देता है:

sum = lambda x, y, z: x + y + z 

curried संस्करण

curriedSum = lambda x: lambda y: lambda z: x + y + z 

मुझे यकीन है कि आप की तरह अजगर कोड नहीं लिख होता है। आईएमओ की प्रेरणा करीबी सैद्धांतिक हित में है। (केवल यूनरी फ़ंक्शंस का उपयोग करके गणनाओं को व्यक्त करने का एक ढांचा: प्रत्येक फ़ंक्शन एकजुट है!) व्यावहारिक उपज यह है कि, उन भाषाओं में जहां फ़ंक्शंस का पीछा किया जाता है, कुछ आंशिक अनुप्रयोग (जब आप बाईं ओर से तर्कों को ठीक करते हैं) उतना ही छोटा होता है करीबी समारोह के लिए तर्क की आपूर्ति। (लेकिन सभी आंशिक अनुप्रयोग इस तरह के नहीं हैं। उदाहरण: दिया गया एफ (एक्स, वाई, जेड) = एक्स + 2 * वाई + 3 * जेड, जब आप वाई चर को दो चर के एक समारोह को उत्पन्न करने के लिए बाध्य करते हैं।) तो आप कह सकते हैं, करी एक ऐसी तकनीक है जो अभ्यास में और उपज के रूप में, कई उपयोगी आंशिक कार्यात्मक अनुप्रयोगों को तुच्छ बना सकती है, लेकिन यह करी की बात नहीं है।

1

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

1

क्लोजर एक भाषा में आवश्यक कार्यक्षमता नहीं हैं। मैं एक घर का बना भाषा प्रयोग कर रहा हूं, lambdatalk, जिसमें लैम्बडा बंद नहीं करते हैं लेकिन आंशिक आवेदन स्वीकार करते हैं। उदाहरण के लिए यह कैसे सेट [विपक्ष, कार, सीडीआर] स्कीम में परिभाषित किया जा सकता है:

(def cons (lambda (x y) (lambda (m) (m x y)))) 
(def car (lambda (z) (z (lambda (p q) p)))) 
(def cdr (lambda (z) (z (lambda (p q) q)))) 

(car (cons 12 34)) -> 12 
(cdr (cons 12 34)) -> 34 

और lambdatalk में:

{def cons {lambda {:x :y :m} {:m :x :y}}} 
{def car {lambda {:z} {:z {lambda {:x :y} :x}}}} 
{def cdr {lambda {:z} {:z {lambda {:x :y} :y}}}} 

{car {cons 12 34}} -> 12 
{cdr {cons 12 34}} -> 34 

योजना में बाहरी लैम्ब्डा को बंद करने में x और y की बचत होती है आंतरिक लैम्ब्डा दिए गए एम तक पहुंच सकते हैं। लैम्बडाटक में लैम्ब्डा बचाता है: एक्स और: वाई और एक नया लैम्ब्डा इंतजार कर रहा है: एम। इसलिए, अगर बंद (और लेक्सिकल स्कोप) उपयोगी कार्यशीलता भी हैं, तो आवश्यकता नहीं है। किसी भी मुक्त चर के बिना, किसी भी शब्दावली के दायरे से, कार्य किसी वास्तविक दुष्प्रभाव के बाद, कुल स्वतंत्रता में, बिना किसी दुष्प्रभाव के काले काले बक्से हैं। क्या आपको ऐसा नहीं लगता?

संबंधित मुद्दे