क्लोजर (कंप्यूटर प्रोग्रामिंग): Difference between revisions
No edit summary |
No edit summary |
||
Line 3: | Line 3: | ||
{{distinguish|text=प्रोग्रामिंग भाषा [[क्लोजर]]}} | {{distinguish|text=प्रोग्रामिंग भाषा [[क्लोजर]]}} | ||
[[प्रोग्रामिंग भाषा|प्रोग्रामिंग भाषाओं]] में, '''क्लोजर''', '''शाब्दिक क्लोजर''' या '''फंक्शन क्लोजर''' भी प्रथम श्रेणी के | [[प्रोग्रामिंग भाषा|प्रोग्रामिंग भाषाओं]] में, '''क्लोजर''', '''शाब्दिक क्लोजर''' या '''फंक्शन क्लोजर''' भी प्रथम श्रेणी के समारोह के साथ भाषा में [[लेक्सिकली स्कोप्ड|शाब्दिकी विस्तार]] [[नाम बंधन]] को प्रयुक्त करने की तकनीक है। क्रियात्मक रूप से [[परिचालन शब्दार्थ]], क्लोजर [[रिकॉर्ड (कंप्यूटर विज्ञान)]] है। जो [[समारोह (कंप्यूटर विज्ञान)]] को पर्यावरण के साथ संग्रहित करता है।<ref>Sussman and Steele. "Scheme: An interpreter for extended lambda calculus". "... a data structure containing a lambda expression, and an environment to be used when that lambda expression is applied to arguments." ([[s:Page:Scheme - An interpreter for extended lambda calculus.djvu/22|Wikisource]])</ref> चूँकि पर्यावरण मानचित्रण है। जो समारोह के प्रत्येक [[मुक्त चर]] को जोड़ता है। (चर जो स्थानीय रूप से उपयोग किए जाते हैं। किन्तु संलग्न चक्र में परिभाषित होते हैं।) अतः [[मूल्य (कंप्यूटर विज्ञान)]] या [[संदर्भ (कंप्यूटर विज्ञान)]] के साथ जिसका नाम बंधन होने पर नाम बाध्य बनाया गया था।{{efn|These names most frequently refer to values, mutable variables, or functions, but can also be other entities such as constants, types, classes, or labels.}} सामान्यतः साधारण समारोह के विपरीत, क्लोजर समारोह को कैप्चर किए गए चरों को उनके मूल्यों या संदर्भों की क्लोजर प्रतियों के माध्यम से प्रवेश करने की अनुमति देता है, तथापि जब समारोह को उनके चक्र से बाहर वर्णित किया जाता है। | ||
[[Category: Templates Vigyan Ready]] | [[Category: Templates Vigyan Ready]] | ||
== इतिहास और व्युत्पत्त == | == इतिहास और व्युत्पत्त == | ||
क्लोजर की अवधारणा को सन्न 1960 के दशक में λ-कैलकुलस में भावों के यांत्रिक मूल्यांकन के लिए विकसित किया गया था और प्रथम बार सन्न 1970 में पूर्ण प्रकार से आरपीएल प्रोग्रामिंग भाषा में भाषा सुविधा के रूप में प्रयुक्त किया गया था। जिससे कि लेक्सिक रूप से प्रथम श्रेणी के | क्लोजर की अवधारणा को सन्न 1960 के दशक में λ-कैलकुलस में भावों के यांत्रिक मूल्यांकन के लिए विकसित किया गया था और प्रथम बार सन्न 1970 में पूर्ण प्रकार से आरपीएल प्रोग्रामिंग भाषा में भाषा सुविधा के रूप में प्रयुक्त किया गया था। जिससे कि लेक्सिक रूप से प्रथम श्रेणी के समारोह का समर्थन किया जा सकता है।<ref name=dat2012>[[David A. Turner]] (2012). [http://www.cs.kent.ac.uk/people/staff/dat/tfp12/tfp12.pdf "Some History of Functional Programming Languages"]. Trends in Functional Programming '12. Section 2, note 8 contains the claim about M-expressions.</ref> | ||
पीटर जे. लैंडिन ने सन्न 1964 में टर्म क्लोजर को पर्यावरण भाग और नियंत्रण भाग के रूप में परिभाषित किया था। जैसा कि अभिव्यक्ति के मूल्यांकन के लिए उनकी एसईसीडी मशीन द्वारा उपयोग किया जाता है।<ref name="landin">{{citation | पीटर जे. लैंडिन ने सन्न 1964 में टर्म क्लोजर को पर्यावरण भाग और नियंत्रण भाग के रूप में परिभाषित किया था। जैसा कि अभिव्यक्ति के मूल्यांकन के लिए उनकी एसईसीडी मशीन द्वारा उपयोग किया जाता है।<ref name="landin">{{citation | ||
Line 16: | Line 16: | ||
{{further|अनाम समारोह}} | {{further|अनाम समारोह}} | ||
क्लोजर शब्द का प्रयोग अधिकांशतः अज्ञात | क्लोजर शब्द का प्रयोग अधिकांशतः अज्ञात समारोह के समानार्थी के रूप में किया जाता है। चूंकि सख्ती से, अज्ञात समारोह के नाम के बिना समारोह [[शाब्दिक (कंप्यूटर प्रोग्रामिंग)]] होता है। जिससे कि क्लोजर समारोह का उदाहरण है। मान (कंप्यूटर विज्ञान), जिसका गैर -स्थानीय चर या तो मूल्यों या [[चर (कंप्यूटर विज्ञान)]] के लिए बाध्य हैं या भंडारण स्थानों के लिए (भाषा के आधार पर नीचे शाब्दिक वातावरण अनुभाग देखें)। | ||
उदाहरण के लिए, निम्नलिखित [[पायथन (प्रोग्रामिंग भाषा)]] कोड में, | उदाहरण के लिए, निम्नलिखित [[पायथन (प्रोग्रामिंग भाषा)]] कोड में, | ||
Line 39: | Line 39: | ||
# प्रथम चर से आबद्ध किए बिना क्लोजर का उपयोग करना। | # प्रथम चर से आबद्ध किए बिना क्लोजर का उपयोग करना। | ||
सामान्यतः <code>a</code> और <code>b</code> के मान क्लोजर है। जो दोनों स्थितियों में स्थिर | सामान्यतः <code>a</code> और <code>b</code> के मान क्लोजर है। जो दोनों स्थितियों में स्थिर समारोह को एन्क्लोजिंग समारोह से मुक्त चर के साथ लौटाकर उत्पादित किया जाता है। जिससे कि मुक्त चर संलग्न समारोह के पैरामीटर <code>x</code> के मान से जुड़ जाता है। चूँकि <code>a</code> और <code>b</code> में बंद कार्यात्मक रूप से समान हैं। कार्यान्वयन में एकमात्र अंतर यह है कि प्रथम स्थितियों में हमने नाम, <code>g</code> के साथ स्थिर समारोह का उपयोग नाम के साथ किया था। (अज्ञात समारोह बनाने के लिए पाइथन संकेत शब्द <code>लैम्ब्डा</code>का उपयोग करके) उन्हें परिभाषित करने में प्रयुक्त मूल नाम, यदि कोई हो, वह अप्रासंगिक है। | ||
क्लोजर किसी भी अन्य मान की भांति मान है। इसके चर को नियुक्त करने की आवश्यकता नहीं है और इसके अतिरिक्त इसे सीधे उपयोग किया जा सकता है। जैसा कि उदाहरण की अंतिम दो पंक्तियों में दिखाया गया है। इस उपयोग को अनाम क्लोजर माना जा सकता है। | क्लोजर किसी भी अन्य मान की भांति मान है। इसके चर को नियुक्त करने की आवश्यकता नहीं है और इसके अतिरिक्त इसे सीधे उपयोग किया जा सकता है। जैसा कि उदाहरण की अंतिम दो पंक्तियों में दिखाया गया है। इस उपयोग को अनाम क्लोजर माना जा सकता है। | ||
चूँकि स्थिर | चूँकि स्थिर समारोह परिभाषाएं स्वयं क्लोजर नहीं हैं। उनके समीप मुक्त चर है। जो अभी तक बाध्य नहीं है। अतः केवल संलग्न समारोह का मूल्यांकन पैरामीटर के मान के साथ किया जाता है। स्थिर समारोह सीमित का मुक्त चर होता है। जो क्लोजर बनाता है। जिसे पश्चात् में संलग्न समारोह से लौटाया जाता है। | ||
अंत में, गैर-स्थानीय चर के चक्र से बाहर होने पर क्लोजर केवल मुक्त चर वाले | अंत में, गैर-स्थानीय चर के चक्र से बाहर होने पर क्लोजर केवल मुक्त चर वाले समारोह से प्रथक होता है। अन्यथा परिभाषित वातावरण और नष्पादन वातावरण से मेल खाते हैं और इन्हें प्रथक करने के लिए कुछ भी नहीं है। (स्थैतिक और गतिशील बाध्यकारी को प्रथक नहीं किया जा सकता है। जिससे कि नाम समान मानों को हल करते हैं।) उदाहरण के लिए, नीचे दिए गए प्रोग्राम में, मुक्त चर <code>x</code> (वैश्विक सीमा के साथ गैर-स्थानीय चर <code>x</code> के लिए बाध्य) वाले कार्यो को उसी वातावरण में निष्पादित किया जाता हैं। जहाँ <code>x</code> को परिभाषित किया गया है। अतः यह सारहीन है कि क्या ये वास्तव में बंद हैं। | ||
एक्स = 1 | एक्स = 1 | ||
Line 58: | Line 58: | ||
नक्शा (लैम्ब्डा वाई, एक्स + वाई, अंक) | नक्शा (लैम्ब्डा वाई, एक्स + वाई, अंक) | ||
यह अधिकांशतः | यह अधिकांशतः समारोह रिटर्न द्वारा प्राप्त किया जाता है। चूँकि समारोह को गैर-स्थानीय चर के चक्र में परिभाषित किया जाना चाहिए। इस स्थितियों में सामान्यतः इसका चक्र छोटा होता है। <code>g</code> | ||
यह [[चर छायांकन]] (जो गैर-स्थानीय चर के चक्र को कम करता है।) द्वारा भी प्राप्त किया जा सकता है। चूंकि व्यवहार में यह कम साधारण है। | यह [[चर छायांकन]] (जो गैर-स्थानीय चर के चक्र को कम करता है।) द्वारा भी प्राप्त किया जा सकता है। चूंकि व्यवहार में यह कम साधारण है। चूंकि यह कम उपयोगी है और छायांकन को हतोत्साहित किया जाता है। इस उदाहरण में <code>f</code> क्लोजर के रूप में देखा जा सकता है। जिससे कि <code>f</code> के शरीर में <code>x</code> वैश्विक नाम स्थान में <code>x</code> के लिए बाध्य है न कि <code>x</code> स्थानीय के लिए <code>g</code> होता है। | ||
एक्स = 0 | एक्स = 0 | ||
Line 74: | Line 74: | ||
== अनुप्रयोग == | == अनुप्रयोग == | ||
क्लोजर का उपयोग उन भाषाओं से जुड़ा हुआ है। जहां कार्य [[प्रथम श्रेणी की वस्तु|प्रथम श्रेणी की वस्तुएं]] हैं। जिसमें उच्च-क्रम के | क्लोजर का उपयोग उन भाषाओं से जुड़ा हुआ है। जहां कार्य [[प्रथम श्रेणी की वस्तु|प्रथम श्रेणी की वस्तुएं]] हैं। जिसमें उच्च-क्रम के समारोह के परिणाम के रूप में समारोह को वापस किया जा सकता है या अन्य समारोह कॉलों के लिए तर्क के रूप में पारित किया जा सकता है। यदि मुक्त चर वाले कार्य प्रथम श्रेणी के हैं। तब वापस लौटने से बंद हो जाता है। इसमें लिस्प (प्रोग्रामिंग भाषा) और [[एमएल (प्रोग्रामिंग भाषा)]], जैसी [[कार्यात्मक प्रोग्रामिंग भाषाएं|कार्यात्मक प्रोग्रामिंग भाषाओं]] के साथ-साथ जूलिया, पायथन और रस्ट जैसी कई आधुनिक, बहु-प्रतिमान भाषाएं सम्मिलित हैं। [[कॉलबैक (कंप्यूटर प्रोग्रामिंग)]] के साथ क्लोजर का भी अधिकांशतः उपयोग किया जाता है। विशेष रूप से [[आयोजन प्रबंधकर्ता]] के लिए, जैसे कि [[जावास्क्रिप्ट]] में, जहां उनका उपयोग [[गतिशील वेब पेज]] के साथ बातचीत के लिए किया जाता है। | ||
सूचनाओं को छिपाने के लिए क्लोजर का उपयोग [[निरंतरता-गुजरने वाली शैली]] में भी किया जा सकता है। [[वस्तु (कंप्यूटर विज्ञान)]] और [[नियंत्रण संरचना]] | सूचनाओं को छिपाने के लिए क्लोजर का उपयोग [[निरंतरता-गुजरने वाली शैली]] में भी किया जा सकता है। [[वस्तु (कंप्यूटर विज्ञान)|वस्तुओं (कंप्यूटर विज्ञान)]] और [[नियंत्रण संरचना|नियंत्रण संरचनाओं]] जैसे निर्माण इस प्रकार बंद होने के साथ प्रयुक्त किए जा सकते हैं। कुछ भाषाओं में, क्लोजर तब हो सकता है, जब समारोह को दूसरे समारोह के अंदर परिभाषित किया जाता है और आंतरिक समारोह बाहरी समारोह के स्थानीय चर को संदर्भित करता है। कार्यावधि (प्रोग्राम जीवनचक्र चरण) पर जब बाहरी समारोह निष्पादित होता है, तब क्लोजर बनता है। जिसमें आंतरिक समारोह का कोड और क्लोजर के लिए आवश्यक बाहरी समारोह के किसी भी चर के संदर्भ (अपमान) होते हैं। | ||
=== प्रथम श्रेणी के कार्य === | === प्रथम श्रेणी के कार्य === | ||
{{further|प्रथम श्रेणी समारोह}} | {{further|प्रथम श्रेणी समारोह}} | ||
क्लोजर सामान्यतः प्रथम श्रेणी के | क्लोजर सामान्यतः प्रथम श्रेणी के समारोह के साथ भाषाओं में दिखाई देते हैं। चूँकि दूसरे शब्दों में, ऐसी भाषाएं समारोह को तर्कों के रूप में पारित करने में सक्षम बनाती हैं। अतः समारोह कॉल से वापस आती हैंऔर चर नामों से बंधी होती हैं इत्यादि। साधारण रूप से जैसे शृंखला के प्रकार और पूर्णांक होते है। उदाहरण के लिए, निम्नलिखित योजना (प्रोग्रामिंग भाषा) समारोह पर विचार कर सकते है। | ||
; विक्रय गई कम से कम सीमा प्रतियों वाली सभी पुस्तकों की सूची लौटाएं। | |||
; | (परिभाषित करें (सर्वाधिक विक्रय होने वाली पुस्तकों की सीमा) | ||
(परिभाषित करें (सर्वाधिक | |||
(फ़िल्टर | (फ़िल्टर | ||
(लैम्ब्डा (पुस्तक) | (लैम्ब्डा (पुस्तक) | ||
(>= (पुस्तक-बिक्री बही) सीमा)) | (>= (पुस्तक-बिक्री बही) सीमा)) | ||
पुस्तक सूची)) | पुस्तक सूची)) | ||
</ | इस उदाहरण में, [[लैम्ब्डा (प्रोग्रामिंग)]] <code>(लैम्ब्डा (पुस्तक) {>= (पुस्तक-बिक्री पुस्तक) सीमा)}</code> समारोह में प्रकट होता है <code>श्रेष्ठ-बिक्री-पुस्तक</code>. जब लैम्ब्डा अभिव्यक्ति का मूल्यांकन किया जाता है। तब योजना लैम्ब्डा अभिव्यक्ति के लिए कोड और संदर्भ के लिए क्लोजर बनाती है <code>सीमा</code> चर, जो लैम्ब्डा अभिव्यक्ति के अंदर मुक्त चर है। | ||
इसके पश्चात् क्लोजर को समीप कर दिया जाता है <code>निस्पंदन</code> समारोह, जो यह निर्धारित करने के लिए बार-बार कॉल करता है कि परिणाम सूची में कौन सी पुस्तकें जोड़ी जानी हैं और कौन सी छोड़ी जानी हैं। चूंकि बंद करने का ही संदर्भ है <code>सीमा</code>, यह अधिकांशतः उस चर का उपयोग कर सकता है <code>निस्पंदन</code> इसे कहते हैं। कार्यक्रम <code>निस्पंदन</code> स्वयं को पूर्ण प्रकार से भिन्न फ़ाइल में परिभाषित किया जा सकता है। | |||
यहाँ उसी उदाहरण को जावास्क्रिप्ट में फिर से लिखा गया है, क्लोजर के लिए समर्थन के साथ अन्य लोकप्रिय भाषा | |||
विक्रय की गई कम से कम 'दहलीज' प्रतियों वाली सभी पुस्तकों की सूची को वापस करना होता है। | |||
सबसे अधिक विक्रय होने वाली पुस्तकें (दहलीज) कार्य करें { | |||
सबसे अधिक | |||
रिटर्न बुकलिस्ट.फ़िल्टर ( | रिटर्न बुकलिस्ट.फ़िल्टर ( | ||
समारोह (पुस्तक) {पुस्तक वापस करें। बिक्री> = सीमा; } | समारोह (पुस्तक) {पुस्तक वापस करें। बिक्री> = सीमा; } | ||
); | ); | ||
} | } | ||
<code>समारोह</code> की जगह यहाँ e> कीवर्ड का प्रयोग किया गया है <code>लैम्ब्डा</code>, और <code>ऐरे.निस्पंदन</code> विधि<ref>{{cite web | url = https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/filter | title = array.filter | work = Mozilla Developer Center | date = 10 January 2010 | access-date = 2010-02-09}}</ref> वैश्विक के अतिरिक्त <code>निस्पंदन</code> कार्य करता है, किन्तु अन्यथा संरचना और कोड का प्रभाव समान होता है। | |||
समारोह क्लोजर बना सकता है और इसे वापस कर सकता है, जैसा कि निम्नलिखित उदाहरण में है: | |||
// समारोह लौटाएं जो f के व्युत्पन्न का अनुमान लगाता है | |||
// डीएक्स के अंतराल का उपयोग करना, जो उचित रूप से छोटा होना चाहिए। | // डीएक्स के अंतराल का उपयोग करना, जो उचित रूप से छोटा होना चाहिए। | ||
समारोह डेरिवेटिव (एफ, डीएक्स) { | |||
वापसी समारोह (एक्स) { | वापसी समारोह (एक्स) { | ||
रिटर्न (एफ(एक्स + डीएक्स) - एफ(एक्स)) / डीएक्स; | रिटर्न (एफ(एक्स + डीएक्स) - एफ(एक्स)) / डीएक्स; | ||
}; | }; | ||
} | } | ||
चूंकि इस स्थितियों में क्लोजर समारोह के निष्पादन को समाप्त कर देता है जो इसे बनाता है, चर <code>f</code> और <code>dx</code> समारोह के पश्चात् लाइव <code>व्युत्पन्न</code> रिटर्न, यदि निष्पादन ने अपना दायरा छोड़ दिया हो और वे अब दिखाई नहीं दे रहे हैं। क्लोजर के बिना भाषाओं में, स्वचालित स्थानीय चर का जीवनकाल स्टैक फ्रेम के निष्पादन के साथ मेल खाता है जहां उस चर को घोषित किया जाता है। क्लोजर वाली भाषाओं में, चर तब तक उपस्तिथ रहना चाहिए जब तक कि किसी भी उपस्तिथा क्लोजर में उनके संदर्भ हों। यह सामान्यतः किसी प्रकार के [[कचरा संग्रह (कंप्यूटर विज्ञान)]] का उपयोग करके कार्यान्वित किया जाता है। | |||
=== राज्य प्रतिनिधित्व === | === राज्य प्रतिनिधित्व === | ||
किसी | किसी समारोह को [[वर्ग (कंप्यूटर प्रोग्रामिंग)]] चर के सेट के साथ जोड़ने के लिए क्लोजर का उपयोग किया जा सकता है, जो समारोह के कई आमंत्रणों पर बना रहता है। चर का दायरा (प्रोग्रामिंग) केवल बंद-ओवर समारोह को सम्मिलित करता है, अतः इसे अन्य प्रोग्राम कोड से अनुलेख नहीं किया जा सकता है। ये [[ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग]] में [[निजी चर]] के अनुरूप हैं, और वास्तव में क्लोजर प्रकार के ऑब्जेक्ट (कंप्यूटर विज्ञान) के अनुरूप हैं, विशेष रूप से [[समारोह वस्तु]], सार्वजनिक विधि (समारोह कॉल) के साथ, और संभवतः कई निजी चर (बंद) -ओवर चरों)। | ||
स्टेटफुल | स्टेटफुल भाषा में, क्लोजर का उपयोग राज्य के प्रतिनिधित्व और सूचनाओं को छिपाने के लिए प्रतिमानों को प्रयुक्त करने के लिए किया जा सकता है, चूंकि क्लोजर के अपमान (इसके बंद-ओवर चरों) अनिश्चित चर (प्रोग्रामिंग) # विस्तार और हद के होते हैं, अतः इनवोकेशन में स्थापित मूल्य बना रहता है अगले में उपलब्ध है। इस प्रकार से उपयोग किए जाने वाले क्लोजर में अब संदर्भित पारदर्शिता नहीं है, और इस प्रकार अब [[शुद्ध समारोह]] नहीं हैं; फिर भी, वे सामान्यतः अशुद्ध कार्यात्मक भाषाओं जैसे स्कीम (प्रोग्रामिंग भाषा) में उपयोग किए जाते हैं। | ||
=== अन्य उपयोग === | === अन्य उपयोग === | ||
क्लोजर के कई उपयोग हैं: | क्लोजर के कई उपयोग हैं: | ||
* | * चूंकि बंद होने से मूल्यांकन में देरी होती है—अर्थात्, वे तब तक कुछ नहीं करते जब तक उन्हें बुलाया नहीं जाता—उनका उपयोग नियंत्रण संरचनाओं को परिभाषित करने के लिए किया जा सकता है। उदाहरण के लिए, स्मॉलटाक की सभी मानक नियंत्रण संरचनाएँ, जिनमें शाखाएँ (यदि/तब/अन्य) और लूप्स (जबकि और के लिए) सम्मिलित हैं, उन वस्तुओं का उपयोग करके परिभाषित की जाती हैं जिनके तरीके क्लोजर स्वीकार करते हैं। उपयोक्ता अपनी स्वयं की नियंत्रण संरचनाओं को भी आसानी से परिभाषित कर सकते हैं। | ||
* उन भाषाओं में जो नियुक्त मेंट को प्रयुक्त करती हैं, ही वातावरण के करीब कई | * उन भाषाओं में जो नियुक्त मेंट को प्रयुक्त करती हैं, ही वातावरण के करीब कई समारोह उत्पन्न किए जा सकते हैं, जिससे वे उस वातावरण को परिवर्तित करके निजी तौर पर संवाद करने में सक्षम हो जाते हैं। योजना में: | ||
(फू #f परिभाषित करें) | (फू #f परिभाषित करें) | ||
(बार #f परिभाषित करें) | (बार #f परिभाषित करें) | ||
Line 138: | Line 139: | ||
(प्रदर्शन (बार)); प्रिंट कोई नहीं | (प्रदर्शन (बार)); प्रिंट कोई नहीं | ||
(नई पंक्ति) | (नई पंक्ति) | ||
(आधी रात को मुझे गोदी से मिलो) | (आधी रात को मुझे गोदी से मिलो) | ||
(प्रदर्शन (बार)); प्रिंट मुझसे आधी रात को डॉक पर मिलते हैं | (प्रदर्शन (बार)); प्रिंट मुझसे आधी रात को डॉक पर मिलते हैं | ||
* | * नामांकन-उन्मुख प्रोग्रामिंग सिस्टम को प्रयुक्त करने के लिए क्लोजर का उपयोग किया जा सकता है।<ref>{{cite web | url = http://okmij.org/ftp/Scheme/oop-in-fp.txt | title = Re: FP, OO and relations. Does anyone trump the others? | date = 29 December 1999 | access-date = 2008-12-23 | archive-url = https://web.archive.org/web/20081226055307/http://okmij.org/ftp/Scheme/oop-in-fp.txt | archive-date = 26 December 2008 | url-status = dead }}</ref> | ||
नोट: कुछ समया किसी भी डेटा संरचना को कॉल करते हैं जो | नोट: कुछ समया किसी भी डेटा संरचना को कॉल करते हैं जो विस्तार (प्रोग्रामिंग) # शाब्दिक विस्तार वातावरण को क्लोजर से बांधता है, किन्तु यह शब्द सामान्यतः विशेष रूप से फ़ंक्शंस को संदर्भित करता है। | ||
== कार्यान्वयन और सिद्धांत == | == कार्यान्वयन और सिद्धांत == | ||
क्लोजर सामान्यतः विशेष डेटा संरचना के साथ कार्यान्वित किया जाता है जिसमें [[समारोह सूचक]] होता है, साथ ही | क्लोजर सामान्यतः विशेष डेटा संरचना के साथ कार्यान्वित किया जाता है जिसमें [[समारोह सूचक]] होता है, साथ ही समारोह के शाब्दिक पर्यावरण (अर्थात, उपलब्ध चर का सेट) का प्रतिनिधित्व उस समय होता है जब क्लोजर बनाया गया था। सन्दर्भ देने वाला पर्यावरण नाम गैर-स्थानीय नामों को शाब्दिक वातावरण में संगत चरों के साथ बांधता है, जब क्लोजर बनाया जाता है, इसके अतिरिक्त उनके जीवनकाल को कम से कम क्लोजर के जीवनकाल तक विस्तारित करता है। जब क्लोजर को पश्चात् के समय में अंकित किया जाता है, संभवतः अलग शाब्दिक वातावरण के साथ, समारोह को इसके गैर-स्थानीय चर के साथ निष्पादित किया जाता है, जो कि क्लोजर द्वारा कब्जा कर लिया गया है, न कि वर्तमान वातावरण। | ||
भाषा कार्यान्वयन आसानी से पूर्ण क्लोजर का समर्थन नहीं कर सकता है यदि इसका | भाषा कार्यान्वयन आसानी से पूर्ण क्लोजर का समर्थन नहीं कर सकता है यदि इसका कार्यावधि मेमोरी मॉडल रैखिक [[स्टैक-आधारित मेमोरी आवंटन]] पर सभी [[स्वचालित चर]] आवंटित करता है। ऐसी भाषाओं में, समारोह के वापस आने पर किसी समारोह के स्वचालित स्थानीय चरों को हटा दिया जाता है। चूँकि, क्लोजर के लिए यह आवश्यक है कि इसके द्वारा संदर्भित नि: शुल्क चरों संलग्न फंक्शन के निष्पादन से बचे रहें। अतः, उन चरों को आवंटित किया जाना चाहिए जिससे कि वे तब तक बने रहें जब तक कि उनकी आवश्यकता न हो, सामान्यतः स्टैक के अतिरिक्त हीप आवंटन के माध्यम से, और उनके जीवनकाल को प्रबंधित किया जाना चाहिए जिससे कि वे तब तक जीवित रहें जब तक कि उन्हें संदर्भित करने वाले सभी क्लोजर अब उपयोग में न हों। | ||
यह बताता है कि क्यों, सामान्यतः, मूल रूप से क्लोजर का समर्थन करने वाली भाषाएं कचरा संग्रह (कंप्यूटर विज्ञान) का उपयोग करती हैं। विकल्प गैर-स्थानीय चर के मैनुअल मेमोरी प्रबंधन हैं (स्पष्ट रूप से हीप पर आवंटन और किए जाने पर मुक्त), या, यदि स्टैक आवंटन का उपयोग करते हैं, तो भाषा के लिए यह स्वीकार करने के लिए कि कुछ उपयोग के स्थितियों [[अपरिभाषित व्यवहार]] की ओर ले जाएंगे, लटकने वाले पॉइंटर्स के कारण सी ++ 11 में लैम्ब्डा अभिव्यक्ति के रूप में मुक्त स्वचालित चर<ref>''[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2550.pdf Lambda Expressions and Closures]'' C++ Standards Committee. 29 February 2008.</ref> या | यह बताता है कि क्यों, सामान्यतः, मूल रूप से क्लोजर का समर्थन करने वाली भाषाएं कचरा संग्रह (कंप्यूटर विज्ञान) का उपयोग करती हैं। विकल्प गैर-स्थानीय चर के मैनुअल मेमोरी प्रबंधन हैं (स्पष्ट रूप से हीप पर आवंटन और किए जाने पर मुक्त), या, यदि स्टैक आवंटन का उपयोग करते हैं, तो भाषा के लिए यह स्वीकार करने के लिए कि कुछ उपयोग के स्थितियों [[अपरिभाषित व्यवहार]] की ओर ले जाएंगे, लटकने वाले पॉइंटर्स के कारण सी ++ 11 में लैम्ब्डा अभिव्यक्ति के रूप में मुक्त स्वचालित चर<ref>''[http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2550.pdf Lambda Expressions and Closures]'' C++ Standards Committee. 29 February 2008.</ref> या जीएनयू सी में स्थिर फ़ंक्शंस।<ref>GCC Manual, [https://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html 6.4 Nested Functions], "If you try to call the nested function through its address after the containing function exits, all hell breaks loose. If you try to call it after a containing scope level exits, and if it refers to some of the variables that are no longer in scope, you may be lucky, but it's not wise to take the risk. If, however, the nested function does not refer to anything that has gone out of scope, you should be safe."</ref> funarg समस्या (या कार्यात्मक तर्क समस्या) सी या सी ++ जैसी स्टैक-आधारित प्रोग्रामिंग भाषा में प्रथम श्रेणी की वस्तुओं के रूप में समारोह को प्रयुक्त करने में कठिनाई का वर्णन करती है। इसी प्रकार [[डी (प्रोग्रामिंग भाषा)]] वर्जन 1 में, यह माना जाता है कि प्रोग्रामर जानता है कि [[प्रतिनिधिमंडल (प्रोग्रामिंग)]] और स्वचालित स्थानीय चर के साथ क्या करना है, चूंकि इसकी परिभाषा के चक्र से लौटने के पश्चात् उनके संदर्भ अमान्य हो जाएंगे (स्वचालित स्थानीय चर ढेर पर हैं) ) - यह अभी भी कई उपयोगी कार्यात्मक पैटर्न की अनुमति देता है, किन्तु जटिल स्थितियों के लिए चर के लिए स्पष्ट हीप आवंटन की आवश्यकता होती है। डी संस्करण 2 ने यह पता लगाने के द्वारा हल किया कि कौन से चर को ढेर पर संग्रहीत किया जाना चाहिए, और स्वचालित आवंटन करता है। चूंकि डी कचरा संग्रह का उपयोग करता है, दोनों संस्करणों में, चर के उपयोग को ट्रैक करने की कोई आवश्यकता नहीं है चूंकि वे समीप हो गए हैं। | ||
अपरिवर्तनीय डेटा (जैसे एरलांग (प्रोग्रामिंग भाषा)) के साथ सख्त कार्यात्मक भाषाओं में, स्वचालित मेमोरी प्रबंधन (कचरा संग्रह) को प्रयुक्त करना बहुत आसान है, | अपरिवर्तनीय डेटा (जैसे एरलांग (प्रोग्रामिंग भाषा)) के साथ सख्त कार्यात्मक भाषाओं में, स्वचालित मेमोरी प्रबंधन (कचरा संग्रह) को प्रयुक्त करना बहुत आसान है, चूंकि चर के संदर्भों में कोई संभावित चक्र नहीं हैं। उदाहरण के लिए, एरलांग में, सभी तर्क और चर ढेर पर आवंटित किए जाते हैं, किन्तु उनके संदर्भ अतिरिक्त रूप से ढेर पर संग्रहीत होते हैं। समारोह के वापस आने के पश्चात्, संदर्भ अभी भी मान्य हैं। वृद्धिशील कचरा संग्राहक द्वारा हीप की सफाई की जाती है। | ||
एमएल में, स्थानीय चर लेक्सिक रूप से स्कॉप्ड होते हैं, और अतः स्टैक-जैसे मॉडल को परिभाषित करते हैं, किन्तु चूंकि वे मूल्यों के लिए बाध्य हैं और वस्तुओं के लिए नहीं, कार्यान्वयन इन मानों को क्लोजर की डेटा संरचना में कॉपी करने के लिए स्वतंत्र है जो कि अदृश्य है प्रोग्रामर। | एमएल में, स्थानीय चर लेक्सिक रूप से स्कॉप्ड होते हैं, और अतः स्टैक-जैसे मॉडल को परिभाषित करते हैं, किन्तु चूंकि वे मूल्यों के लिए बाध्य हैं और वस्तुओं के लिए नहीं, कार्यान्वयन इन मानों को क्लोजर की डेटा संरचना में कॉपी करने के लिए स्वतंत्र है जो कि अदृश्य है प्रोग्रामर। | ||
स्कीम (प्रोग्रामिंग | स्कीम (प्रोग्रामिंग भाषा), जिसमें गतिशील चरों और कचरा संग्रह के साथ [[ALGOL]] जैसी शाब्दिक विस्तार सिस्टम है, में स्टैक प्रोग्रामिंग मॉडल का अभाव है और यह स्टैक-आधारित भाषाओं की सीमाओं से ग्रस्त नहीं है। योजना में क्लोजर स्वाभाविक रूप से व्यक्त किए जाते हैं। लैम्ब्डा फॉर्म कोड को संलग्न करता है, और इसके पर्यावरण के मुक्त चर कार्यक्रम के भीतर तब तक बने रहते हैं जब तक उन्हें संभवतः अनुलेख किया जा सकता है, और अतः उन्हें किसी अन्य योजना अभिव्यक्ति के रूप में स्वतंत्र रूप से उपयोग किया जा सकता है। | ||
क्लोजर समवर्ती संगणना के [[अभिनेता मॉडल]] में अभिनेताओं से निकटता से संबंधित हैं, जहां | |||
क्लोजर | क्लोजर समवर्ती संगणना के [[अभिनेता मॉडल]] में अभिनेताओं से निकटता से संबंधित हैं, जहां समारोह के शाब्दिक वातावरण में मूल्यों को परिचित कहा जाता है। [[समवर्ती प्रोग्रामिंग]] भाषाओं में क्लोजर के लिए महत्वपूर्ण मुद्दा यह है कि क्या क्लोजर में चरों को अपडेट किया जा सकता है और यदि हां, तो इन अद्यतन को कैसे समक्रमिक किया जा सकता है। अभिनेता समाधान प्रदान करते हैं।<ref>''[https://dspace.mit.edu/handle/1721.1/6935 Foundations of Actor Semantics]'' Will Clinger. MIT Mathematics Doctoral Dissertation. June 1981.</ref> | ||
क्लोजर समारोह ऑब्जेक्ट्स से निकटता से संबंधित हैं; पूर्व से दूसरे में परिवर्तन को [[निष्क्रियता]] या [[लैम्ब्डा उठाना]] के रूप में जाना जाता है; क्लोजर रूपांतरण भी देखें। | |||
== शब्दार्थ में अंतर == | == शब्दार्थ में अंतर == | ||
=== शाब्दिक वातावरण === | === शाब्दिक वातावरण === | ||
जैसा कि | जैसा कि भिन्न-भिन्न भाषाओं में हमेशा शाब्दिक वातावरण की सामान्य परिभाषा नहीं होती है, उनके बंद होने की परिभाषा भी भिन्न हो सकती है। शाब्दिक पर्यावरण की सामान्य रूप से आयोजित न्यूनतम परिभाषा इसे चक्र में बाध्यकारी सभी नामों के सेट के रूप में परिभाषित करती है, और यह भी कि किसी भी भाषा में बंद होने पर कब्जा करना पड़ता है। चूँकि [[चर (प्रोग्रामिंग)]] आबद्धिंग का अर्थ भी भिन्न होता है। अनिवार्य भाषाओं में, चर स्मृति में सापेक्ष स्थानों से जुड़ते हैं जो मूल्यों को संग्रहीत कर सकते हैं। चूँकि आबद्धिंग का सापेक्ष स्थान कार्यावधि पर नहीं परिवर्तितता है, किन्तु सीमित स्थिति में मान परिवर्तित सकता है। ऐसी भाषाओं में, चूंकि क्लोजर आबद्धिंग को कैप्चर करता है, चर पर कोई भी ऑपरेशन, चाहे क्लोजर से किया गया हो या नहीं, उसी रिलेटिव मेमोरी स्थिति पर किया जाता है। इसे अधिकांशतः चर को संदर्भ द्वारा कैप्चर करना कहा जाता है। यहां ईसीएमएस्क्रिप्ट में अवधारणा को चित्रित करने वाला उदाहरण दिया गया है, जो ऐसी ही भाषा है: | ||
// जावास्क्रिप्ट | // जावास्क्रिप्ट | ||
वार एफ, जी | वार एफ, जी, | ||
समारोह फू () { | समारोह फू () { | ||
वार एक्स; | वार एक्स; | ||
Line 175: | Line 180: | ||
चेतावनी ('फू के अंदर, एफ को कॉल करें):' + एफ ()); | चेतावनी ('फू के अंदर, एफ को कॉल करें):' + एफ ()); | ||
} | } | ||
फू (); // 2 | फू (); // 2 | ||
चेतावनी ('जी को कॉल करें):' + जी ()); // 1 (--x) | चेतावनी ('जी को कॉल करें):' + जी ()); // 1 (--x) | ||
चेतावनी ('जी को कॉल करें):' + जी ()); // 0 (--x) | चेतावनी ('जी को कॉल करें):' + जी ()); // 0 (--x) | ||
चेतावनी ('कॉल टू एफ ():' + एफ ()); // 1 (++x) | चेतावनी ('कॉल टू एफ ():' + एफ ()); // 1 (++x) | ||
चेतावनी ('कॉल टू एफ ():' + एफ ()); // 2 (++x) | चेतावनी ('कॉल टू एफ ():' + एफ ()); // 2 (++x) | ||
समारोह <code> | समारोह <code>फू</code> और चरों द्वारा संदर्भित क्लोजर <code>f</code> और <code>g</code> सभी स्थानीय चर द्वारा दर्शाए गए समान सापेक्ष स्मृति स्थान का उपयोग करते हैं <code>x</code>. | ||
कुछ उदाहरणों में उपरोक्त व्यवहार अवांछनीय हो सकता है, और अलग शाब्दिक समापन को बांधना आवश्यक है। फिर से ईसीएमएस्क्रिप्ट में, इसका उपयोग करके किया जाएगा <code>समारोह.bind()</code>. | |||
=== उदाहरण 1: अनसीमित चर === का संदर्भ<ref>{{cite web |title=Function.prototype.bind() |url=https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind |website=MDN Web Docs |access-date=20 November 2018}}</ref> | |||
वार मॉड्यूल = { | वार मॉड्यूल = { | ||
एक्स: 42, | एक्स: 42, | ||
getX: | getX: समारोह () {इसे वापस करें। x; } | ||
} | } | ||
var अनसीमितगेटएक्स = मॉड्यूल.गेटएक्स; | var अनसीमितगेटएक्स = मॉड्यूल.गेटएक्स; | ||
कंसोल.लॉग (अनसीमितगेटएक्स ()); // | कंसोल.लॉग (अनसीमितगेटएक्स ()); // समारोह को वैश्विक चक्र में प्रयुक्त किया जाता है | ||
// अपरिभाषित उत्सर्जित करता है | // अपरिभाषित उत्सर्जित करता है चूंकि 'x' वैश्विक चक्र में निर्दिष्ट नहीं है। | ||
var सीमितगेटएक्स = अनसीमितगेटएक्स.आबद्ध (मॉड्यूल); // ऑब्जेक्ट मॉड्यूल को क्लोजर के रूप में निर्दिष्ट करें | var सीमितगेटएक्स = अनसीमितगेटएक्स.आबद्ध (मॉड्यूल); // ऑब्जेक्ट मॉड्यूल को क्लोजर के रूप में निर्दिष्ट करें | ||
Line 203: | Line 211: | ||
=== उदाहरण 2: बाध्य चर के लिए आकस्मिक संदर्भ === | === उदाहरण 2: बाध्य चर के लिए आकस्मिक संदर्भ === | ||
इस उदाहरण के लिए अपेक्षित व्यवहार यह होगा कि क्लिक किए जाने पर प्रत्येक लिंक को अपनी आईडी छोड़नी चाहिए; किन्तु | इस उदाहरण के लिए अपेक्षित व्यवहार यह होगा कि क्लिक किए जाने पर प्रत्येक लिंक को अपनी आईडी छोड़नी चाहिए; किन्तु चूंकि चर 'ई' उपरोक्त चक्र से जुड़ा हुआ है, और क्लिक पर आलसी मूल्यांकन किया गया है, वास्तव में क्या होता है कि प्रत्येक क्लिक ईवेंट अंतिम तत्व की आईडी को लूप के अंत में बंधे 'तत्व' में उत्सर्जित करता है।<ref>{{cite web |title=Closures |url=https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures#Creating_closures_in_loops_A_common_mistake |website=MDN Web Docs |access-date=20 November 2018}}</ref> | ||
var एलिमेंट्स = document.getElementsByTagName ('ए') | <वाक्यविन्यास लैंग = एक्मास्क्रिप्ट> | ||
// गलत: ई 'फॉर' लूप वाले | |||
के लिए (तत्वों का संस्करण) {e.onclick = | var एलिमेंट्स = document.getElementsByTagName ('ए') | ||
</ | |||
यहाँ फिर से परिवर्तनशील | <nowiki>// गलत: ई 'फॉर' लूप वाले समारोह के लिए बाध्य है, न कि हैंडल को बंद करने के लिए | ||
के लिए (तत्वों का संस्करण) {e.onclick = समारोह हैंडल () {अलर्ट (e.id);}}</nowiki> | |||
यहाँ फिर से परिवर्तनशील <code>e</code> का उपयोग करके ब्लॉक के चक्र से बंधे होने की आवश्यकता होगी <code>handle.bind(this)</code> या <code>let</code> कीवर्ड। | |||
दूसरी ओर, कई कार्यात्मक भाषाएं, जैसे एमएल (प्रोग्रामिंग भाषा), चर को सीधे मानों से बांधती हैं। इस स्थितियों में, चूंकि बार बाध्य होने के पश्चात् चर के मान को | दूसरी ओर, कई कार्यात्मक भाषाएं, जैसे एमएल (प्रोग्रामिंग भाषा), चर को सीधे मानों से बांधती हैं। इस स्थितियों में, चूंकि बार बाध्य होने के पश्चात् चर के मान को परिवर्तितने का कोई विधि नहीं है, राज्य को बंद करने के बीच साझा करने की कोई आवश्यकता नहीं है - वे केवल उसी मान का उपयोग करते हैं। इसे अधिकांशतः चर को मान द्वारा कैप्चर करना कहा जाता है। जावा के स्थानीय और अनाम वर्ग भी इस श्रेणी में आते हैं - उन्हें होने के लिए कैप्चर किए गए स्थानीय चर की आवश्यकता होती है <code>final</code>, जिसका अर्थ यह भी है कि राज्य को साझा करने की कोई आवश्यकता नहीं है। | ||
कुछ भाषाएँ आपको चर या उसके स्थान के मान को कैप्चर करने के बीच चयन करने में सक्षम बनाती हैं। उदाहरण के लिए, सी ++ 11 में, कैप्चर किए गए चर या तो घोषित किए जाते हैं <code>[&]</code>, जिसका अर्थ है संदर्भ द्वारा या साथ में कब्जा कर लिया गया <code>[=]</code>, जिसका अर्थ है मूल्य द्वारा कब्जा कर लिया गया। | कुछ भाषाएँ आपको चर या उसके स्थान के मान को कैप्चर करने के बीच चयन करने में सक्षम बनाती हैं। उदाहरण के लिए, सी ++ 11 में, कैप्चर किए गए चर या तो घोषित किए जाते हैं <code>[&]</code>, जिसका अर्थ है संदर्भ द्वारा या साथ में कब्जा कर लिया गया <code>[=]</code>, जिसका अर्थ है मूल्य द्वारा कब्जा कर लिया गया। | ||
Line 218: | Line 229: | ||
<वाक्यविन्यास लैंग = हैकेल> | <वाक्यविन्यास लैंग = हैकेल> | ||
-- हास्केल | -- हास्केल | ||
फू :: भिन्नात्मक a => a -> a -> (a -> a) | |||
फू x y = (\z -> z + r) | फू x y = (\z -> z + r) | ||
जहां आर = एक्स / वाई | जहां आर = एक्स / वाई | ||
Line 229: | Line 241: | ||
</वाक्यविन्यास हाइलाइट> | </वाक्यविन्यास हाइलाइट> | ||
का बंधन <code>r</code> | का बंधन <code>r</code> समारोह के भीतर परिभाषित क्लोजर द्वारा कैप्चर किया गया <code>फू</code> गणना के लिए है <code>(x / y)</code>—जो इस स्थितियों में शून्य से विभाजन में परिणत होता है। चूँकि, चूंकि यह अभिकलन है जो कैप्चर किया गया है, न कि मान, त्रुटि केवल तभी प्रकट होती है जब क्लोजर का आह्वान किया जाता है, और वास्तव में कैप्चर किए गए आबद्धिंग का उपयोग करने का प्रयास करता है। | ||
=== जा रहा बंद === | === जा रहा बंद === | ||
फिर भी अधिक अंतर स्वयं को अन्य व्याख्यात्मक रूप से निर्मित निर्माणों के व्यवहार में प्रकट करते हैं, जैसे कि <code>return</code>, <code>break</code> और <code>continue</code> कथन। इस प्रकार के निर्माण, सामान्य रूप से, संलग्न नियंत्रण विवरण (के स्थितियों में) द्वारा स्थापित पलायन निरंतरता को प्रयुक्त करने के संदर्भ में माना जा सकता है <code>break</code> और <code>continue</code>, इस प्रकार की व्याख्या के लिए पुनरावर्ती | फिर भी अधिक अंतर स्वयं को अन्य व्याख्यात्मक रूप से निर्मित निर्माणों के व्यवहार में प्रकट करते हैं, जैसे कि <code>return</code>, <code>break</code> और <code>continue</code> कथन। इस प्रकार के निर्माण, सामान्य रूप से, संलग्न नियंत्रण विवरण (के स्थितियों में) द्वारा स्थापित पलायन निरंतरता को प्रयुक्त करने के संदर्भ में माना जा सकता है <code>break</code> और <code>continue</code>, इस प्रकार की व्याख्या के लिए पुनरावर्ती समारोह कॉल के संदर्भ में लूपिंग निर्माणों पर विचार करने की आवश्यकता होती है)। कुछ भाषाओं में, जैसे ईसीएमएस्क्रिप्ट, <code>return</code> कथन के संबंध में व्याख्यात्मक रूप से आंतरिक रूप से क्लोजर द्वारा स्थापित निरंतरता को संदर्भित करता है- इस प्रकार, ए <code>return</code> क्लोजर के भीतर उस कोड को नियंत्रण स्थानांतरित करता है जिसने इसे बुलाया था। चूँकि, स्मॉलटॉक में, सतही रूप से समान ऑपरेटर <code>^</code> किसी भी हस्तक्षेप करने वाले स्थिर क्लोजर के एस्केप निरंतरता को अनदेखा करते हुए, विधि आमंत्रण के लिए स्थापित एस्केप निरंतरता को आमंत्रित करता है। क्लोजर के कोड के अंत तक पहुंचकर किसी विशेष क्लोजर की एस्केप निरंतरता को केवल स्मॉलटाक में प्रयुक्त किया जा सकता है। ईसीएमएस्क्रिप्ट और स्मॉलटाक में निम्नलिखित उदाहरण अंतर को उजागर करते हैं: | ||
<वाक्यविन्यास लैंग = स्मॉलटॉक> | <वाक्यविन्यास लैंग = स्मॉलटॉक> | ||
Line 249: | Line 261: | ||
समारोह फू () { | समारोह फू () { | ||
वार xs = [1, 2, 3, 4]; | वार xs = [1, 2, 3, 4]; | ||
xs.forEach ( | xs.forEach (समारोह (x) {वापसी x;}); | ||
वापसी 0; | वापसी 0; | ||
} | } | ||
Line 255: | Line 267: | ||
</वाक्यविन्यास हाइलाइट> | </वाक्यविन्यास हाइलाइट> | ||
उपरोक्त कोड स्निपेट्स अलग प्रकार से व्यवहार करेंगे | उपरोक्त कोड स्निपेट्स अलग प्रकार से व्यवहार करेंगे चूंकि स्मॉलटाक <code>^</code> ऑपरेटर और जावास्क्रिप्ट <code>return</code> ऑपरेटर अनुरूप नहीं हैं। ईसीएमएस्क्रिप्ट उदाहरण में, <code>return x</code> का नया पुनरावृति प्रारंभ करने के लिए आंतरिक समापन को छोड़ देगा <code>forEach</code> पाश, जबकि स्मालटाक उदाहरण में, <code>^x</code> लूप को निरस्त कर देगा और विधि से वापस आ जाएगा <code>फू</code>. | ||
[[सामान्य लिस्प]] निर्माण प्रदान करता है जो उपरोक्त | [[सामान्य लिस्प]] निर्माण प्रदान करता है जो उपरोक्त समारोह में से किसी को व्यक्त कर सकता है: लिस्प <code>(return-from फू x)</code> स्मॉलटाक के रूप में व्यवहार करता है <code>^x</code>, जबकि लिस्प <code>(return-from nil x)</code> जावास्क्रिप्ट के रूप में व्यवहार करता है <code>return x</code>. अतः, स्मॉलटॉक कैप्चर किए गए एस्केप निरंतरता को उस सीमा तक जीवित रहने के लिए संभव बनाता है जिसमें इसे सफलतापूर्वक प्रयुक्त किया जा सकता है। विचार करना: | ||
<वाक्यविन्यास लैंग = स्मॉलटॉक> | <वाक्यविन्यास लैंग = स्मॉलटॉक> | ||
Line 269: | Line 281: | ||
</वाक्यविन्यास हाइलाइट> | </वाक्यविन्यास हाइलाइट> | ||
जब बंद विधि द्वारा वापस आ गया <code> | जब बंद विधि द्वारा वापस आ गया <code>फू</code> आह्वान किया जाता है, यह के आह्वान से मान वापस करने का प्रयास करता है <code>फू</code> जिसने बंद बनाया। चूँकि वह कॉल पहले ही वापस आ चुकी है और स्मॉलटाक विधि मंगलाचरण मॉडल कई रिटर्न की सुविधा के लिए [[स्पेगेटी ढेर]] अनुशासन का पालन नहीं करता है, इस ऑपरेशन के परिणामस्वरूप त्रुटि होती है। | ||
कुछ भाषाएँ, जैसे [[रूबी (प्रोग्रामिंग भाषा)]], प्रोग्रामर को रास्ता चुनने में सक्षम बनाती हैं <code>return</code> कब्जा कर लिया है। रूबी में उदाहरण: | कुछ भाषाएँ, जैसे [[रूबी (प्रोग्रामिंग भाषा)]], प्रोग्रामर को रास्ता चुनने में सक्षम बनाती हैं <code>return</code> कब्जा कर लिया है। रूबी में उदाहरण: | ||
Line 278: | Line 290: | ||
# प्रोक का उपयोग कर बंद करें | # प्रोक का उपयोग कर बंद करें | ||
डेफ फू | डेफ फू | ||
f = Proc.new { | f = Proc.new { फू से अंदर की खरीद से वापसी वापसी} | ||
f.call # control फू को यहां छोड़ देता है | f.call # control फू को यहां छोड़ देता है | ||
फू से वापसी | फू से वापसी | ||
Line 294: | Line 306: | ||
</वाक्यविन्यास हाइलाइट> | </वाक्यविन्यास हाइलाइट> | ||
दोनों <code>Proc.new</code> और <code> | दोनों <code>Proc.new</code> और <code>लैम्ब्डा</code> इस उदाहरण में क्लोजर बनाने के तरीके हैं, किन्तु इस प्रकार से बनाए गए क्लोजर के शब्दार्थ इसके संबंध में भिन्न हैं <code>return</code> कथन। | ||
स्कीम (प्रोग्रामिंग | स्कीम (प्रोग्रामिंग भाषा) में, की परिभाषा और कार्यक्षेत्र <code>return</code> नियंत्रण कथन स्पष्ट है (और उदाहरण के लिए केवल मनमाने ढंग से 'वापसी' नाम दिया गया है)। निम्नलिखित रूबी नमूने का सीधा अनुवाद है। | ||
<वाक्यविन्यास लैंग = योजना> | <वाक्यविन्यास लैंग = योजना> | ||
Line 328: | Line 340: | ||
[[कॉलबैक (कंप्यूटर विज्ञान)]] एस। यह है | [[कॉलबैक (कंप्यूटर विज्ञान)]] एस। यह है | ||
कभी-कभी दो मान प्रदान करके कार्यान्वित किया जाता है जब | कभी-कभी दो मान प्रदान करके कार्यान्वित किया जाता है जब | ||
लाइब्रेरी के साथ कॉलबैक पंजीकृत करना: | लाइब्रेरी के साथ कॉलबैक पंजीकृत करना: समारोह | ||
सूचक और अलग <code>void*</code> के लिए सूचक | सूचक और अलग <code>void*</code> के लिए सूचक | ||
उपयोगकर्ता की पसंद का मनमाना डेटा। जब पुस्तकालय | उपयोगकर्ता की पसंद का मनमाना डेटा। जब पुस्तकालय | ||
कॉलबैक | कॉलबैक समारोह निष्पादित करता है, यह डेटा के साथ गुजरता है | ||
सूचक। यह कॉलबैक को राज्य और बनाए रखने में सक्षम बनाता है | सूचक। यह कॉलबैक को राज्य और बनाए रखने में सक्षम बनाता है | ||
उस समय कैप्चर की गई जानकारी को संदर्भित करने के लिए | उस समय कैप्चर की गई जानकारी को संदर्भित करने के लिए | ||
Line 342: | Line 354: | ||
सामान्य को जोड़कर [[घटना-संचालित प्रोग्रामिंग]] प्रयुक्त करें | सामान्य को जोड़कर [[घटना-संचालित प्रोग्रामिंग]] प्रयुक्त करें | ||
ग्राफिकल विगेट्स के कार्य (मेनू, बटन, चेक बॉक्स, | ग्राफिकल विगेट्स के कार्य (मेनू, बटन, चेक बॉक्स, | ||
स्लाइडर्स, स्पिनर्स, आदि) एप्लिकेशन-विशिष्ट | स्लाइडर्स, स्पिनर्स, आदि) एप्लिकेशन-विशिष्ट समारोह के साथ | ||
आवेदन के लिए विशिष्ट वांछित व्यवहार को प्रयुक्त करना। | आवेदन के लिए विशिष्ट वांछित व्यवहार को प्रयुक्त करना। | ||
==== स्थिर | ==== स्थिर समारोह और समारोह पॉइंटर (सी) ==== | ||
जीसीसी विस्तार के साथ, [https://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html स्थिर | जीसीसी विस्तार के साथ, [https://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html स्थिर समारोह] का उपयोग किया जा सकता है और समारोह पॉइंटर क्लोजर का अनुकरण कर सकता है, बशर्ते समारोह युक्त चक्र से बाहर न हो। | ||
निम्न उदाहरण अमान्य है | निम्न उदाहरण अमान्य है चूंकि <code>adder</code> शीर्ष-स्तरीय परिभाषा है (संकलक संस्करण के आधार पर, यह अनुकूलन के बिना संकलित होने पर सही परिणाम उत्पन्न कर सकता है, अर्थात <code>-O0</code>): | ||
<वाक्यविन्यास प्रकाश लैंग = सी> | <वाक्यविन्यास प्रकाश लैंग = सी> | ||
#सम्मिलित <stdio.h> | #सम्मिलित <stdio.h> | ||
टाइपपीफ इंट (*fn_int_to_int)(int); // | टाइपपीफ इंट (*fn_int_to_int)(int); // समारोह का प्रकार int->int | ||
fn_int_to_int योजक (पूर्णांक संख्या) { | fn_int_to_int योजक (पूर्णांक संख्या) { | ||
इंट ऐड (इंट मान) { रिटर्न मान + नंबर; } | इंट ऐड (इंट मान) { रिटर्न मान + नंबर; } | ||
वापसी और जोड़ें; // और ऑपरेटर यहाँ वैकल्पिक है | वापसी और जोड़ें; // और ऑपरेटर यहाँ वैकल्पिक है चूंकि C में समारोह का नाम पॉइंटर है जो स्वयं की ओर इशारा करता है | ||
} | } | ||
Line 372: | Line 384: | ||
पूर्णांक मुख्य (शून्य) { | पूर्णांक मुख्य (शून्य) { | ||
टाइपपीफ इंट (*fn_int_to_int)(int); // | टाइपपीफ इंट (*fn_int_to_int)(int); // समारोह का प्रकार int->int | ||
fn_int_to_int योजक (पूर्णांक संख्या) { | fn_int_to_int योजक (पूर्णांक संख्या) { | ||
Line 394: | Line 406: | ||
निजी अस्थिर इंट परिणाम; | निजी अस्थिर इंट परिणाम; | ||
// ... | // ... | ||
सार्वजनिक शून्य गणना | सार्वजनिक शून्य गणना भिन्न-भिन्न थ्रेड (अंतिम यूआरआई यूरी) { | ||
// अभिव्यक्ति नया रननेबल () {...} 'रननेबल' इंटरफ़ेस को प्रयुक्त करने वाला अनाम वर्ग है। | // अभिव्यक्ति नया रननेबल () {...} 'रननेबल' इंटरफ़ेस को प्रयुक्त करने वाला अनाम वर्ग है। | ||
नया सूत्र( | नया सूत्र( | ||
Line 412: | Line 424: | ||
का कब्जा <code>final</code> चरों आपको मान द्वारा चरों को कैप्चर करने में सक्षम बनाता है। यदि आप जिस चर को कैप्चर करना चाहते हैं वह गैर-<code>final</code>, आप इसे हमेशा अस्थायी में कॉपी कर सकते हैं <code>final</code> कक्षा से ठीक पहले परिवर्तनशील। | का कब्जा <code>final</code> चरों आपको मान द्वारा चरों को कैप्चर करने में सक्षम बनाता है। यदि आप जिस चर को कैप्चर करना चाहते हैं वह गैर-<code>final</code>, आप इसे हमेशा अस्थायी में कॉपी कर सकते हैं <code>final</code> कक्षा से ठीक पहले परिवर्तनशील। | ||
रेफरेंस द्वारा चरों को कैप्चर करने का उपयोग करके अनुकरण किया जा सकता है <code>final</code> परिवर्तनशील कंटेनर का संदर्भ, उदाहरण के लिए, एकल-तत्व सरणी। स्थानीय वर्ग स्वयं कंटेनर संदर्भ के मूल्य को | रेफरेंस द्वारा चरों को कैप्चर करने का उपयोग करके अनुकरण किया जा सकता है <code>final</code> परिवर्तनशील कंटेनर का संदर्भ, उदाहरण के लिए, एकल-तत्व सरणी। स्थानीय वर्ग स्वयं कंटेनर संदर्भ के मूल्य को परिवर्तितने में सक्षम नहीं होगा, किन्तु यह कंटेनर की सामग्री को परिवर्तितने में सक्षम होगा। | ||
जावा 8 के लैम्ब्डा भावों के आगमन के साथ,<ref>{{cite web | जावा 8 के लैम्ब्डा भावों के आगमन के साथ,<ref>{{cite web | ||
Line 423: | Line 435: | ||
निजी अस्थिर इंट परिणाम; | निजी अस्थिर इंट परिणाम; | ||
// ... | // ... | ||
सार्वजनिक शून्य गणना | सार्वजनिक शून्य गणना भिन्न-भिन्न थ्रेड (अंतिम यूआरआई यूरी) { | ||
// कोड () -> { /* कोड */} क्लोजर है। | // कोड () -> { /* कोड */} क्लोजर है। | ||
नया थ्रेड (() -> { | नया थ्रेड (() -> { | ||
Line 477: | Line 489: | ||
निष्पादन पर, यह 0 से 9 तक के पूर्णांकों को प्रिंट करेगा। इस प्रकार के वर्ग को स्थिर वर्ग के साथ भ्रमित न करने के लिए सावधान रहें, जो उसी प्रकार से घोषित किया जाता है जैसे स्थैतिक संशोधक के उपयोग के साथ; उनका वांछित प्रभाव नहीं है, बल्कि केवल वे वर्ग हैं जिनके समीप संलग्न वर्ग में परिभाषित कोई विशेष बंधन नहीं है। | निष्पादन पर, यह 0 से 9 तक के पूर्णांकों को प्रिंट करेगा। इस प्रकार के वर्ग को स्थिर वर्ग के साथ भ्रमित न करने के लिए सावधान रहें, जो उसी प्रकार से घोषित किया जाता है जैसे स्थैतिक संशोधक के उपयोग के साथ; उनका वांछित प्रभाव नहीं है, बल्कि केवल वे वर्ग हैं जिनके समीप संलग्न वर्ग में परिभाषित कोई विशेष बंधन नहीं है। | ||
जावा संस्करण इतिहास#Java_8 के रूप में, जावा प्रथम श्रेणी की वस्तुओं के रूप में | जावा संस्करण इतिहास#Java_8 के रूप में, जावा प्रथम श्रेणी की वस्तुओं के रूप में समारोह का समर्थन करता है। इस रूप के लैम्ब्डा भावों को प्रकार का माना जाता है <code>समारोह<T,U></code> जहां T डोमेन है और U छवि प्रकार है। इसके साथ व्यंजक कहा जा सकता है <code>.apply(T t)</code> विधि, किन्तु मानक विधि कॉल के साथ नहीं। | ||
<वाक्यविन्यास प्रकाश लैंग = जावा> | <वाक्यविन्यास प्रकाश लैंग = जावा> | ||
Line 509: | Line 521: | ||
=== प्रतिनिधि (सी #, वीबी.नेट, डी) === | === प्रतिनिधि (सी #, वीबी.नेट, डी) === | ||
सी शार्प (प्रोग्रामिंग | सी शार्प (प्रोग्रामिंग भाषा) | सी # अनाम तरीके और लैम्ब्डा अभिव्यक्ति क्लोजर का समर्थन करते हैं: | ||
<वाक्यविन्यास प्रकाश लैंग = csharp> | <वाक्यविन्यास प्रकाश लैंग = csharp> | ||
Line 522: | Line 534: | ||
मंद डेटा = {1, 2, 3, 4} | मंद डेटा = {1, 2, 3, 4} | ||
मंद गुणक = 2 | मंद गुणक = 2 | ||
मंद परिणाम = डेटा। चयन करें ( | मंद परिणाम = डेटा। चयन करें (समारोह (x) x * गुणक) | ||
</वाक्यविन्यास हाइलाइट> | </वाक्यविन्यास हाइलाइट> | ||
डी (प्रोग्रामिंग | डी (प्रोग्रामिंग भाषा) में, क्लोजर को डेलीगेट्स द्वारा प्रयुक्त किया जाता है, फंक्शन पॉइंटर को कॉन्टेक्स्ट पॉइंटर के साथ जोड़ा जाता है (उदाहरण के लिए क्लास इंस्टेंस, या क्लोजर के स्थितियों में हीप पर स्टैक फ्रेम)। | ||
<वाक्यविन्यास प्रकाश लैंग = डी> | <वाक्यविन्यास प्रकाश लैंग = डी> | ||
Line 548: | Line 560: | ||
</वाक्यविन्यास हाइलाइट> | </वाक्यविन्यास हाइलाइट> | ||
D संस्करण 1 में सीमित क्लोजर समर्थन है। उदाहरण के लिए, उपरोक्त कोड सही ढंग से काम नहीं करेगा, | D संस्करण 1 में सीमित क्लोजर समर्थन है। उदाहरण के लिए, उपरोक्त कोड सही ढंग से काम नहीं करेगा, चूंकि चर a स्टैक पर है, और परीक्षण () से लौटने के पश्चात्, यह अब इसका उपयोग करने के लिए मान्य नहीं है (संभवतः डीजी () के माध्यम से फू को कॉल करना, 'वापसी करेगा यादृच्छिक 'पूर्णांक)। इसे ढेर पर चर 'ए' को स्पष्ट रूप से आवंटित करके, या सभी आवश्यक बंद चरों को संग्रहीत करने के लिए स्ट्रक्चर्स या क्लास का उपयोग करके हल किया जा सकता है और उसी कोड को प्रयुक्त करने वाली विधि से प्रतिनिधि का निर्माण किया जा सकता है। क्लोजर को अन्य समारोह में पारित किया जा सकता है, जब तक कि वे केवल तब तक उपयोग किए जाते हैं जब संदर्भित मान अभी भी मान्य होते हैं (उदाहरण के लिए कॉलबैक पैरामीटर के रूप में क्लोजर के साथ किसी अन्य समारोह को कॉल करना), और सामान्य डेटा प्रोसेसिंग कोड लिखने के लिए उपयोगी होते हैं, अतः यह सीमा , व्यवहार में, अधिकांशतः कोई समस्या नहीं होती है। | ||
यह सीमा डी संस्करण 2 में तय की गई थी - चर 'ए' स्वचालित रूप से हीप पर आवंटित किया जाएगा | यह सीमा डी संस्करण 2 में तय की गई थी - चर 'ए' स्वचालित रूप से हीप पर आवंटित किया जाएगा चूंकि इसका उपयोग आंतरिक समारोह में किया जाता है, और उस समारोह का प्रतिनिधि वर्तमान चक्र से बच सकता है (डीजी या वापसी के लिए नियुक्त मेंट के माध्यम से)। कोई भी अन्य स्थानीय चर (या तर्क) जो प्रतिनिधियों द्वारा संदर्भित नहीं हैं या जो केवल प्रतिनिधियों द्वारा संदर्भित हैं जो वर्तमान चक्र से बाहर नहीं निकलते हैं, स्टैक पर बने रहते हैं, जो हीप आवंटन की तुलना में सरल और तेज़ है। आंतरिक वर्ग विधियों के लिए भी यही सच है जो किसी समारोह के चर को संदर्भित करता है। | ||
=== | === समारोह ऑब्जेक्ट्स (सी ++) === | ||
सी ++ ओवरलोडिंग द्वारा फ़ंक्शन ऑब्जेक्ट्स को परिभाषित करने में सक्षम बनाता है <code>operator()</code>. ये ऑब्जेक्ट कुछ हद तक कार्यात्मक प्रोग्रामिंग भाषा में कार्यों की तरह व्यवहार करते हैं। वे रनटाइम पर बनाए जा सकते हैं और इसमें राज्य शामिल हो सकते हैं, लेकिन वे स्थानीय चर को बंद करने के रूप में निहित रूप से कैप्चर नहीं करते हैं। [[सी ++ 11]] के अनुसार, सी ++ भाषा भी क्लोजर का समर्थन करती है, जो एक प्रकार का फ़ंक्शन ऑब्जेक्ट है जो लैम्ब्डा-एक्सप्रेशन नामक एक विशेष भाषा निर्माण से स्वचालित रूप से निर्मित होता है। एक सी ++ क्लोजर क्लोजर ऑब्जेक्ट या संदर्भ के सदस्यों के रूप में एक्सेस किए गए चर की प्रतियों को संग्रहीत करके इसके संदर्भ को कैप्चर कर सकता है। बाद के मामले में, यदि क्लोजर ऑब्जेक्ट संदर्भित ऑब्जेक्ट के दायरे से बाहर निकलता है, तो इसका आह्वान करता है <code>operator()</code> अपरिभाषित व्यवहार का कारण बनता है क्योंकि सी ++ क्लोजर उनके संदर्भ के जीवनकाल का विस्तार नहीं करते हैं।{{main|Anonymous function#C++ (since C++11)}} | सी ++ ओवरलोडिंग द्वारा फ़ंक्शन ऑब्जेक्ट्स को परिभाषित करने में सक्षम बनाता है <code>operator()</code>. ये ऑब्जेक्ट कुछ हद तक कार्यात्मक प्रोग्रामिंग भाषा में कार्यों की तरह व्यवहार करते हैं। वे रनटाइम पर बनाए जा सकते हैं और इसमें राज्य शामिल हो सकते हैं, लेकिन वे स्थानीय चर को बंद करने के रूप में निहित रूप से कैप्चर नहीं करते हैं। [[सी ++ 11]] के अनुसार, सी ++ भाषा भी क्लोजर का समर्थन करती है, जो एक प्रकार का फ़ंक्शन ऑब्जेक्ट है जो लैम्ब्डा-एक्सप्रेशन नामक एक विशेष भाषा निर्माण से स्वचालित रूप से निर्मित होता है। एक सी ++ क्लोजर क्लोजर ऑब्जेक्ट या संदर्भ के सदस्यों के रूप में एक्सेस किए गए चर की प्रतियों को संग्रहीत करके इसके संदर्भ को कैप्चर कर सकता है। बाद के मामले में, यदि क्लोजर ऑब्जेक्ट संदर्भित ऑब्जेक्ट के दायरे से बाहर निकलता है, तो इसका आह्वान करता है <code>operator()</code> अपरिभाषित व्यवहार का कारण बनता है क्योंकि सी ++ क्लोजर उनके संदर्भ के जीवनकाल का विस्तार नहीं करते हैं।{{main|Anonymous function#C++ (since C++11)}} | ||
<वाक्यविन्यास लैंग = सीपीपी> | <वाक्यविन्यास लैंग = सीपीपी> | ||
Line 569: | Line 581: | ||
=== इनलाइन एजेंट (एफिल) === | === इनलाइन एजेंट (एफिल) === | ||
एफिल (प्रोग्रामिंग | एफिल (प्रोग्रामिंग भाषा) में क्लोजर को परिभाषित करने वाले इनलाइन एजेंट सम्मिलित हैं। इनलाइन एजेंट रूटीन का प्रतिनिधित्व करने वाली वस्तु है, जिसे रूटीन इन-लाइन का कोड देकर परिभाषित किया जाता है। उदाहरण के लिए, में | ||
<वाक्यविन्यास लैंग = एफिल> | <वाक्यविन्यास लैंग = एफिल> | ||
Line 580: | Line 592: | ||
को तर्क <code>subscribe</code> एजेंट है, जो दो तर्कों के साथ प्रक्रिया का प्रतिनिधित्व करता है; प्रक्रिया देश को संबंधित निर्देशांक पर ढूंढती है और इसे प्रदर्शित करती है। पूरे एजेंट को ईवेंट प्रकार की सदस्यता दी गई है <code>click_event</code> के लिए | को तर्क <code>subscribe</code> एजेंट है, जो दो तर्कों के साथ प्रक्रिया का प्रतिनिधित्व करता है; प्रक्रिया देश को संबंधित निर्देशांक पर ढूंढती है और इसे प्रदर्शित करती है। पूरे एजेंट को ईवेंट प्रकार की सदस्यता दी गई है <code>click_event</code> के लिए | ||
निश्चित बटन, जिससे कि जब भी उस बटन पर घटना प्रकार का उदाहरण हो - | निश्चित बटन, जिससे कि जब भी उस बटन पर घटना प्रकार का उदाहरण हो - चूंकि उपयोगकर्ता ने बटन पर क्लिक किया है - प्रक्रिया को माउस निर्देशांक के साथ तर्क के रूप में पारित किया जाएगा <code>x</code> और <code>y</code>. | ||
एफिल एजेंटों की मुख्य सीमा, जो उन्हें अन्य भाषाओं में बंद होने से अलग करती है, यह है कि वे स्थानीय चर को संलग्न चक्र से संदर्भित नहीं कर सकते हैं। यह डिज़ाइन निर्णय अस्पष्टता से बचने में मदद करता है जब क्लोजर में स्थानीय चर मान के बारे में बात की जाती है - क्या यह चर का नवीनतम मान होना चाहिए या एजेंट के बनाए जाने पर कैप्चर किया गया मान होना चाहिए? केवल <code>Current</code> (वर्तमान वस्तु का संदर्भ, के अनुरूप <code>this</code> जावा में), इसकी विशेषताओं और एजेंट के तर्कों को एजेंट निकाय के भीतर से ही | एफिल एजेंटों की मुख्य सीमा, जो उन्हें अन्य भाषाओं में बंद होने से अलग करती है, यह है कि वे स्थानीय चर को संलग्न चक्र से संदर्भित नहीं कर सकते हैं। यह डिज़ाइन निर्णय अस्पष्टता से बचने में मदद करता है जब क्लोजर में स्थानीय चर मान के बारे में बात की जाती है - क्या यह चर का नवीनतम मान होना चाहिए या एजेंट के बनाए जाने पर कैप्चर किया गया मान होना चाहिए? केवल <code>Current</code> (वर्तमान वस्तु का संदर्भ, के अनुरूप <code>this</code> जावा में), इसकी विशेषताओं और एजेंट के तर्कों को एजेंट निकाय के भीतर से ही अनुलेख किया जा सकता है। एजेंट को अतिरिक्त बंद ऑपरेंड प्रदान करके बाहरी स्थानीय चर के मान पारित किए जा सकते हैं। | ||
=== सी ++ बिल्डर क्लोजर आरक्षित शब्द === | === सी ++ बिल्डर क्लोजर आरक्षित शब्द === | ||
Embarcadero C++ Builder | Embarcadero C++ Builder समारोह पॉइंटर के समान सिंटैक्स वाली विधि को पॉइंटर प्रदान करने के लिए आरक्षित शब्द _ क्लोजर प्रदान करता है।<ref>Full documentation can be found at http://docwiki.embarcadero.com/RADStudio/Rio/en/Closure</ref> | ||
मानक C में आप a लिख सकते हैं {{mono|[[typedef]]}} निम्नलिखित सिंटैक्स का उपयोग करके | मानक C में आप a लिख सकते हैं {{mono|[[typedef]]}} निम्नलिखित सिंटैक्स का उपयोग करके समारोह प्रकार के सूचक के लिए:<syntaxhighlight lang= c++ > | ||
टाइपपीफ शून्य (*TMyFunctionPointer) (शून्य); | टाइपपीफ शून्य (*TMyFunctionPointer) (शून्य); | ||
</syntaxhighlight>इसी प्रकार से आप घोषित कर सकते हैं a {{mono|typedef}} निम्नलिखित सिंटैक्स का उपयोग करने वाली विधि के लिए सूचक के लिए:<nowiki><syntaxhighlight lang= c++ ></nowiki> | </syntaxhighlight>इसी प्रकार से आप घोषित कर सकते हैं a {{mono|typedef}} निम्नलिखित सिंटैक्स का उपयोग करने वाली विधि के लिए सूचक के लिए:<nowiki><syntaxhighlight lang= c++ ></nowiki> | ||
Line 615: | Line 627: | ||
== बाहरी संबंध == | == बाहरी संबंध == | ||
*[https://web.archive.org/web/20160510140804/http://library.readscheme.org/page1.html Original " | *[https://web.archive.org/web/20160510140804/http://library.readscheme.org/page1.html Original "लैम्ब्डा Papers"]: A classic series of papers by [[Guy Steele]] and [[Gerald Sussman]] discussing, among other things, the versatility of closures in the context of Scheme (where they appear as ''[[lambda calculus|लैम्ब्डा]] expressions''). | ||
* {{cite web | * {{cite web | ||
| author = Neal Gafter | | author = Neal Gafter |
Revision as of 22:20, 22 March 2023
प्रोग्रामिंग भाषाओं में, क्लोजर, शाब्दिक क्लोजर या फंक्शन क्लोजर भी प्रथम श्रेणी के समारोह के साथ भाषा में शाब्दिकी विस्तार नाम बंधन को प्रयुक्त करने की तकनीक है। क्रियात्मक रूप से परिचालन शब्दार्थ, क्लोजर रिकॉर्ड (कंप्यूटर विज्ञान) है। जो समारोह (कंप्यूटर विज्ञान) को पर्यावरण के साथ संग्रहित करता है।[1] चूँकि पर्यावरण मानचित्रण है। जो समारोह के प्रत्येक मुक्त चर को जोड़ता है। (चर जो स्थानीय रूप से उपयोग किए जाते हैं। किन्तु संलग्न चक्र में परिभाषित होते हैं।) अतः मूल्य (कंप्यूटर विज्ञान) या संदर्भ (कंप्यूटर विज्ञान) के साथ जिसका नाम बंधन होने पर नाम बाध्य बनाया गया था।[lower-alpha 1] सामान्यतः साधारण समारोह के विपरीत, क्लोजर समारोह को कैप्चर किए गए चरों को उनके मूल्यों या संदर्भों की क्लोजर प्रतियों के माध्यम से प्रवेश करने की अनुमति देता है, तथापि जब समारोह को उनके चक्र से बाहर वर्णित किया जाता है।
इतिहास और व्युत्पत्त
क्लोजर की अवधारणा को सन्न 1960 के दशक में λ-कैलकुलस में भावों के यांत्रिक मूल्यांकन के लिए विकसित किया गया था और प्रथम बार सन्न 1970 में पूर्ण प्रकार से आरपीएल प्रोग्रामिंग भाषा में भाषा सुविधा के रूप में प्रयुक्त किया गया था। जिससे कि लेक्सिक रूप से प्रथम श्रेणी के समारोह का समर्थन किया जा सकता है।[2]
पीटर जे. लैंडिन ने सन्न 1964 में टर्म क्लोजर को पर्यावरण भाग और नियंत्रण भाग के रूप में परिभाषित किया था। जैसा कि अभिव्यक्ति के मूल्यांकन के लिए उनकी एसईसीडी मशीन द्वारा उपयोग किया जाता है।[3] जोएल मोसेस ने लैम्ब्डा अभिव्यक्ति को संदर्भित करने के लिए क्लोजर शब्द की शुरुआत करने का श्रेय लैंडिन को दिया है। जिसके खुला बंधन (नि: शुल्क चरों) को शाब्दिक वातावरण द्वारा (या आंतरिक) बंद कर दिया गया है। जिसके परिणामस्वरूप बंद अभिव्यक्ति या क्लोजर होता है।[4][5] इस प्रयोग को पश्चात् में गेराल्ड जे सुस्मान और गाइ एल. स्टील, जूनियर द्वारा अपनाया गया था। जब उन्होंने सन्न 1975 में योजना (प्रोग्रामिंग भाषा) को परिभाषित किया था।[6] अतः लिस्प (प्रोग्रामिंग भाषा) का शाब्दिकी विस्तार रूपांतर और व्यापक हो गया है।
सुस्मान और हेरोल्ड एबेलसन भी सन्न 1980 के दशक में दूसरे, असंबंधित अर्थ के साथ क्लोजर शब्द का उपयोग करते हैं। चूँकि ऑपरेटर की संपत्ति जो डेटा संरचना में डेटा जोड़ती है और स्थिर डेटा संरचनाओं को भी जोड़ने में सक्षम होती है। अतः यह शब्द का प्रयोग कंप्यूटर विज्ञान में पूर्व उपयोग के अतिरिक्त क्लोजर (गणित) से आता है। जिसे लेखक शब्दावली में इस ओवरलैप को "दुर्भाग्यपूर्ण" मानते हैं।[7]
अनाम कार्य
क्लोजर शब्द का प्रयोग अधिकांशतः अज्ञात समारोह के समानार्थी के रूप में किया जाता है। चूंकि सख्ती से, अज्ञात समारोह के नाम के बिना समारोह शाब्दिक (कंप्यूटर प्रोग्रामिंग) होता है। जिससे कि क्लोजर समारोह का उदाहरण है। मान (कंप्यूटर विज्ञान), जिसका गैर -स्थानीय चर या तो मूल्यों या चर (कंप्यूटर विज्ञान) के लिए बाध्य हैं या भंडारण स्थानों के लिए (भाषा के आधार पर नीचे शाब्दिक वातावरण अनुभाग देखें)।
उदाहरण के लिए, निम्नलिखित पायथन (प्रोग्रामिंग भाषा) कोड में,
डेफ एफ (एक्स),
डेफ जी (वाई): रिटर्न एक्स + वाई रिटर्न जी # रिटर्न क्लोजर।
डीईएफ़ एच (एक्स)
रिटर्न लैम्ब्डा वाई: एक्स + वाई # क्लोजर लौटाएं।
- चरों को विशिष्ट क्लोजर नियुक्त करना।
ए = एफ (1)
बी = एच (1)
- चरों में संग्रह किए गए क्लोजर का उपयोग करना।
ए (5) == 6 पर जोर दें
जोर बी (5) == 6
- प्रथम चर से आबद्ध किए बिना क्लोजर का उपयोग करना।
सामान्यतः a
और b
के मान क्लोजर है। जो दोनों स्थितियों में स्थिर समारोह को एन्क्लोजिंग समारोह से मुक्त चर के साथ लौटाकर उत्पादित किया जाता है। जिससे कि मुक्त चर संलग्न समारोह के पैरामीटर x
के मान से जुड़ जाता है। चूँकि a
और b
में बंद कार्यात्मक रूप से समान हैं। कार्यान्वयन में एकमात्र अंतर यह है कि प्रथम स्थितियों में हमने नाम, g
के साथ स्थिर समारोह का उपयोग नाम के साथ किया था। (अज्ञात समारोह बनाने के लिए पाइथन संकेत शब्द लैम्ब्डा
का उपयोग करके) उन्हें परिभाषित करने में प्रयुक्त मूल नाम, यदि कोई हो, वह अप्रासंगिक है।
क्लोजर किसी भी अन्य मान की भांति मान है। इसके चर को नियुक्त करने की आवश्यकता नहीं है और इसके अतिरिक्त इसे सीधे उपयोग किया जा सकता है। जैसा कि उदाहरण की अंतिम दो पंक्तियों में दिखाया गया है। इस उपयोग को अनाम क्लोजर माना जा सकता है।
चूँकि स्थिर समारोह परिभाषाएं स्वयं क्लोजर नहीं हैं। उनके समीप मुक्त चर है। जो अभी तक बाध्य नहीं है। अतः केवल संलग्न समारोह का मूल्यांकन पैरामीटर के मान के साथ किया जाता है। स्थिर समारोह सीमित का मुक्त चर होता है। जो क्लोजर बनाता है। जिसे पश्चात् में संलग्न समारोह से लौटाया जाता है।
अंत में, गैर-स्थानीय चर के चक्र से बाहर होने पर क्लोजर केवल मुक्त चर वाले समारोह से प्रथक होता है। अन्यथा परिभाषित वातावरण और नष्पादन वातावरण से मेल खाते हैं और इन्हें प्रथक करने के लिए कुछ भी नहीं है। (स्थैतिक और गतिशील बाध्यकारी को प्रथक नहीं किया जा सकता है। जिससे कि नाम समान मानों को हल करते हैं।) उदाहरण के लिए, नीचे दिए गए प्रोग्राम में, मुक्त चर x
(वैश्विक सीमा के साथ गैर-स्थानीय चर x
के लिए बाध्य) वाले कार्यो को उसी वातावरण में निष्पादित किया जाता हैं। जहाँ x
को परिभाषित किया गया है। अतः यह सारहीन है कि क्या ये वास्तव में बंद हैं।
एक्स = 1
अंक = [ 1, 2, 3 ]
डेफ एफ (वाई),
रिटर्न एक्स + वाई
नक्शा (एफ, अंक)
नक्शा (लैम्ब्डा वाई, एक्स + वाई, अंक)
यह अधिकांशतः समारोह रिटर्न द्वारा प्राप्त किया जाता है। चूँकि समारोह को गैर-स्थानीय चर के चक्र में परिभाषित किया जाना चाहिए। इस स्थितियों में सामान्यतः इसका चक्र छोटा होता है। g
यह चर छायांकन (जो गैर-स्थानीय चर के चक्र को कम करता है।) द्वारा भी प्राप्त किया जा सकता है। चूंकि व्यवहार में यह कम साधारण है। चूंकि यह कम उपयोगी है और छायांकन को हतोत्साहित किया जाता है। इस उदाहरण में f
क्लोजर के रूप में देखा जा सकता है। जिससे कि f
के शरीर में x
वैश्विक नाम स्थान में x
के लिए बाध्य है न कि x
स्थानीय के लिए g
होता है।
एक्स = 0
डेफ एफ (वाई):
रिटर्न एक्स + वाई
डेफ जी (जेड):
x = 1 # स्थानीय x छाया वैश्विक x रिटर्न एफ (जेड)
g(1) # 1 का मूल्यांकन करता है, 2 का नहीं
अनुप्रयोग
क्लोजर का उपयोग उन भाषाओं से जुड़ा हुआ है। जहां कार्य प्रथम श्रेणी की वस्तुएं हैं। जिसमें उच्च-क्रम के समारोह के परिणाम के रूप में समारोह को वापस किया जा सकता है या अन्य समारोह कॉलों के लिए तर्क के रूप में पारित किया जा सकता है। यदि मुक्त चर वाले कार्य प्रथम श्रेणी के हैं। तब वापस लौटने से बंद हो जाता है। इसमें लिस्प (प्रोग्रामिंग भाषा) और एमएल (प्रोग्रामिंग भाषा), जैसी कार्यात्मक प्रोग्रामिंग भाषाओं के साथ-साथ जूलिया, पायथन और रस्ट जैसी कई आधुनिक, बहु-प्रतिमान भाषाएं सम्मिलित हैं। कॉलबैक (कंप्यूटर प्रोग्रामिंग) के साथ क्लोजर का भी अधिकांशतः उपयोग किया जाता है। विशेष रूप से आयोजन प्रबंधकर्ता के लिए, जैसे कि जावास्क्रिप्ट में, जहां उनका उपयोग गतिशील वेब पेज के साथ बातचीत के लिए किया जाता है।
सूचनाओं को छिपाने के लिए क्लोजर का उपयोग निरंतरता-गुजरने वाली शैली में भी किया जा सकता है। वस्तुओं (कंप्यूटर विज्ञान) और नियंत्रण संरचनाओं जैसे निर्माण इस प्रकार बंद होने के साथ प्रयुक्त किए जा सकते हैं। कुछ भाषाओं में, क्लोजर तब हो सकता है, जब समारोह को दूसरे समारोह के अंदर परिभाषित किया जाता है और आंतरिक समारोह बाहरी समारोह के स्थानीय चर को संदर्भित करता है। कार्यावधि (प्रोग्राम जीवनचक्र चरण) पर जब बाहरी समारोह निष्पादित होता है, तब क्लोजर बनता है। जिसमें आंतरिक समारोह का कोड और क्लोजर के लिए आवश्यक बाहरी समारोह के किसी भी चर के संदर्भ (अपमान) होते हैं।
प्रथम श्रेणी के कार्य
क्लोजर सामान्यतः प्रथम श्रेणी के समारोह के साथ भाषाओं में दिखाई देते हैं। चूँकि दूसरे शब्दों में, ऐसी भाषाएं समारोह को तर्कों के रूप में पारित करने में सक्षम बनाती हैं। अतः समारोह कॉल से वापस आती हैंऔर चर नामों से बंधी होती हैं इत्यादि। साधारण रूप से जैसे शृंखला के प्रकार और पूर्णांक होते है। उदाहरण के लिए, निम्नलिखित योजना (प्रोग्रामिंग भाषा) समारोह पर विचार कर सकते है।
- विक्रय गई कम से कम सीमा प्रतियों वाली सभी पुस्तकों की सूची लौटाएं।
(परिभाषित करें (सर्वाधिक विक्रय होने वाली पुस्तकों की सीमा)
(फ़िल्टर (लैम्ब्डा (पुस्तक) (>= (पुस्तक-बिक्री बही) सीमा)) पुस्तक सूची))
इस उदाहरण में, लैम्ब्डा (प्रोग्रामिंग) (लैम्ब्डा (पुस्तक) {>= (पुस्तक-बिक्री पुस्तक) सीमा)}
समारोह में प्रकट होता है श्रेष्ठ-बिक्री-पुस्तक
. जब लैम्ब्डा अभिव्यक्ति का मूल्यांकन किया जाता है। तब योजना लैम्ब्डा अभिव्यक्ति के लिए कोड और संदर्भ के लिए क्लोजर बनाती है सीमा
चर, जो लैम्ब्डा अभिव्यक्ति के अंदर मुक्त चर है।
इसके पश्चात् क्लोजर को समीप कर दिया जाता है निस्पंदन
समारोह, जो यह निर्धारित करने के लिए बार-बार कॉल करता है कि परिणाम सूची में कौन सी पुस्तकें जोड़ी जानी हैं और कौन सी छोड़ी जानी हैं। चूंकि बंद करने का ही संदर्भ है सीमा
, यह अधिकांशतः उस चर का उपयोग कर सकता है निस्पंदन
इसे कहते हैं। कार्यक्रम निस्पंदन
स्वयं को पूर्ण प्रकार से भिन्न फ़ाइल में परिभाषित किया जा सकता है।
यहाँ उसी उदाहरण को जावास्क्रिप्ट में फिर से लिखा गया है, क्लोजर के लिए समर्थन के साथ अन्य लोकप्रिय भाषा
विक्रय की गई कम से कम 'दहलीज' प्रतियों वाली सभी पुस्तकों की सूची को वापस करना होता है।
सबसे अधिक विक्रय होने वाली पुस्तकें (दहलीज) कार्य करें {
रिटर्न बुकलिस्ट.फ़िल्टर ( समारोह (पुस्तक) {पुस्तक वापस करें। बिक्री> = सीमा; } );
}
समारोह
की जगह यहाँ e> कीवर्ड का प्रयोग किया गया है लैम्ब्डा
, और ऐरे.निस्पंदन
विधि[8] वैश्विक के अतिरिक्त निस्पंदन
कार्य करता है, किन्तु अन्यथा संरचना और कोड का प्रभाव समान होता है।
समारोह क्लोजर बना सकता है और इसे वापस कर सकता है, जैसा कि निम्नलिखित उदाहरण में है:
// समारोह लौटाएं जो f के व्युत्पन्न का अनुमान लगाता है
// डीएक्स के अंतराल का उपयोग करना, जो उचित रूप से छोटा होना चाहिए।
समारोह डेरिवेटिव (एफ, डीएक्स) {
वापसी समारोह (एक्स) { रिटर्न (एफ(एक्स + डीएक्स) - एफ(एक्स)) / डीएक्स; };
}
चूंकि इस स्थितियों में क्लोजर समारोह के निष्पादन को समाप्त कर देता है जो इसे बनाता है, चर f
और dx
समारोह के पश्चात् लाइव व्युत्पन्न
रिटर्न, यदि निष्पादन ने अपना दायरा छोड़ दिया हो और वे अब दिखाई नहीं दे रहे हैं। क्लोजर के बिना भाषाओं में, स्वचालित स्थानीय चर का जीवनकाल स्टैक फ्रेम के निष्पादन के साथ मेल खाता है जहां उस चर को घोषित किया जाता है। क्लोजर वाली भाषाओं में, चर तब तक उपस्तिथ रहना चाहिए जब तक कि किसी भी उपस्तिथा क्लोजर में उनके संदर्भ हों। यह सामान्यतः किसी प्रकार के कचरा संग्रह (कंप्यूटर विज्ञान) का उपयोग करके कार्यान्वित किया जाता है।
राज्य प्रतिनिधित्व
किसी समारोह को वर्ग (कंप्यूटर प्रोग्रामिंग) चर के सेट के साथ जोड़ने के लिए क्लोजर का उपयोग किया जा सकता है, जो समारोह के कई आमंत्रणों पर बना रहता है। चर का दायरा (प्रोग्रामिंग) केवल बंद-ओवर समारोह को सम्मिलित करता है, अतः इसे अन्य प्रोग्राम कोड से अनुलेख नहीं किया जा सकता है। ये ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग में निजी चर के अनुरूप हैं, और वास्तव में क्लोजर प्रकार के ऑब्जेक्ट (कंप्यूटर विज्ञान) के अनुरूप हैं, विशेष रूप से समारोह वस्तु, सार्वजनिक विधि (समारोह कॉल) के साथ, और संभवतः कई निजी चर (बंद) -ओवर चरों)।
स्टेटफुल भाषा में, क्लोजर का उपयोग राज्य के प्रतिनिधित्व और सूचनाओं को छिपाने के लिए प्रतिमानों को प्रयुक्त करने के लिए किया जा सकता है, चूंकि क्लोजर के अपमान (इसके बंद-ओवर चरों) अनिश्चित चर (प्रोग्रामिंग) # विस्तार और हद के होते हैं, अतः इनवोकेशन में स्थापित मूल्य बना रहता है अगले में उपलब्ध है। इस प्रकार से उपयोग किए जाने वाले क्लोजर में अब संदर्भित पारदर्शिता नहीं है, और इस प्रकार अब शुद्ध समारोह नहीं हैं; फिर भी, वे सामान्यतः अशुद्ध कार्यात्मक भाषाओं जैसे स्कीम (प्रोग्रामिंग भाषा) में उपयोग किए जाते हैं।
अन्य उपयोग
क्लोजर के कई उपयोग हैं:
- चूंकि बंद होने से मूल्यांकन में देरी होती है—अर्थात्, वे तब तक कुछ नहीं करते जब तक उन्हें बुलाया नहीं जाता—उनका उपयोग नियंत्रण संरचनाओं को परिभाषित करने के लिए किया जा सकता है। उदाहरण के लिए, स्मॉलटाक की सभी मानक नियंत्रण संरचनाएँ, जिनमें शाखाएँ (यदि/तब/अन्य) और लूप्स (जबकि और के लिए) सम्मिलित हैं, उन वस्तुओं का उपयोग करके परिभाषित की जाती हैं जिनके तरीके क्लोजर स्वीकार करते हैं। उपयोक्ता अपनी स्वयं की नियंत्रण संरचनाओं को भी आसानी से परिभाषित कर सकते हैं।
- उन भाषाओं में जो नियुक्त मेंट को प्रयुक्त करती हैं, ही वातावरण के करीब कई समारोह उत्पन्न किए जा सकते हैं, जिससे वे उस वातावरण को परिवर्तित करके निजी तौर पर संवाद करने में सक्षम हो जाते हैं। योजना में:
(फू #f परिभाषित करें)
(बार #f परिभाषित करें)
(चलो ((गुप्त-संदेश कोई नहीं))
(सेट! फू (लैम्ब्डा (संदेश) (सेट! गुप्त-संदेश संदेश))) (सेट! बार (लैम्ब्डा () गुप्त-संदेश)))
(प्रदर्शन (बार)); प्रिंट कोई नहीं
(नई पंक्ति)
(आधी रात को मुझे गोदी से मिलो)
(प्रदर्शन (बार)); प्रिंट मुझसे आधी रात को डॉक पर मिलते हैं
- नामांकन-उन्मुख प्रोग्रामिंग सिस्टम को प्रयुक्त करने के लिए क्लोजर का उपयोग किया जा सकता है।[9]
नोट: कुछ समया किसी भी डेटा संरचना को कॉल करते हैं जो विस्तार (प्रोग्रामिंग) # शाब्दिक विस्तार वातावरण को क्लोजर से बांधता है, किन्तु यह शब्द सामान्यतः विशेष रूप से फ़ंक्शंस को संदर्भित करता है।
कार्यान्वयन और सिद्धांत
क्लोजर सामान्यतः विशेष डेटा संरचना के साथ कार्यान्वित किया जाता है जिसमें समारोह सूचक होता है, साथ ही समारोह के शाब्दिक पर्यावरण (अर्थात, उपलब्ध चर का सेट) का प्रतिनिधित्व उस समय होता है जब क्लोजर बनाया गया था। सन्दर्भ देने वाला पर्यावरण नाम गैर-स्थानीय नामों को शाब्दिक वातावरण में संगत चरों के साथ बांधता है, जब क्लोजर बनाया जाता है, इसके अतिरिक्त उनके जीवनकाल को कम से कम क्लोजर के जीवनकाल तक विस्तारित करता है। जब क्लोजर को पश्चात् के समय में अंकित किया जाता है, संभवतः अलग शाब्दिक वातावरण के साथ, समारोह को इसके गैर-स्थानीय चर के साथ निष्पादित किया जाता है, जो कि क्लोजर द्वारा कब्जा कर लिया गया है, न कि वर्तमान वातावरण।
भाषा कार्यान्वयन आसानी से पूर्ण क्लोजर का समर्थन नहीं कर सकता है यदि इसका कार्यावधि मेमोरी मॉडल रैखिक स्टैक-आधारित मेमोरी आवंटन पर सभी स्वचालित चर आवंटित करता है। ऐसी भाषाओं में, समारोह के वापस आने पर किसी समारोह के स्वचालित स्थानीय चरों को हटा दिया जाता है। चूँकि, क्लोजर के लिए यह आवश्यक है कि इसके द्वारा संदर्भित नि: शुल्क चरों संलग्न फंक्शन के निष्पादन से बचे रहें। अतः, उन चरों को आवंटित किया जाना चाहिए जिससे कि वे तब तक बने रहें जब तक कि उनकी आवश्यकता न हो, सामान्यतः स्टैक के अतिरिक्त हीप आवंटन के माध्यम से, और उनके जीवनकाल को प्रबंधित किया जाना चाहिए जिससे कि वे तब तक जीवित रहें जब तक कि उन्हें संदर्भित करने वाले सभी क्लोजर अब उपयोग में न हों।
यह बताता है कि क्यों, सामान्यतः, मूल रूप से क्लोजर का समर्थन करने वाली भाषाएं कचरा संग्रह (कंप्यूटर विज्ञान) का उपयोग करती हैं। विकल्प गैर-स्थानीय चर के मैनुअल मेमोरी प्रबंधन हैं (स्पष्ट रूप से हीप पर आवंटन और किए जाने पर मुक्त), या, यदि स्टैक आवंटन का उपयोग करते हैं, तो भाषा के लिए यह स्वीकार करने के लिए कि कुछ उपयोग के स्थितियों अपरिभाषित व्यवहार की ओर ले जाएंगे, लटकने वाले पॉइंटर्स के कारण सी ++ 11 में लैम्ब्डा अभिव्यक्ति के रूप में मुक्त स्वचालित चर[10] या जीएनयू सी में स्थिर फ़ंक्शंस।[11] funarg समस्या (या कार्यात्मक तर्क समस्या) सी या सी ++ जैसी स्टैक-आधारित प्रोग्रामिंग भाषा में प्रथम श्रेणी की वस्तुओं के रूप में समारोह को प्रयुक्त करने में कठिनाई का वर्णन करती है। इसी प्रकार डी (प्रोग्रामिंग भाषा) वर्जन 1 में, यह माना जाता है कि प्रोग्रामर जानता है कि प्रतिनिधिमंडल (प्रोग्रामिंग) और स्वचालित स्थानीय चर के साथ क्या करना है, चूंकि इसकी परिभाषा के चक्र से लौटने के पश्चात् उनके संदर्भ अमान्य हो जाएंगे (स्वचालित स्थानीय चर ढेर पर हैं) ) - यह अभी भी कई उपयोगी कार्यात्मक पैटर्न की अनुमति देता है, किन्तु जटिल स्थितियों के लिए चर के लिए स्पष्ट हीप आवंटन की आवश्यकता होती है। डी संस्करण 2 ने यह पता लगाने के द्वारा हल किया कि कौन से चर को ढेर पर संग्रहीत किया जाना चाहिए, और स्वचालित आवंटन करता है। चूंकि डी कचरा संग्रह का उपयोग करता है, दोनों संस्करणों में, चर के उपयोग को ट्रैक करने की कोई आवश्यकता नहीं है चूंकि वे समीप हो गए हैं।
अपरिवर्तनीय डेटा (जैसे एरलांग (प्रोग्रामिंग भाषा)) के साथ सख्त कार्यात्मक भाषाओं में, स्वचालित मेमोरी प्रबंधन (कचरा संग्रह) को प्रयुक्त करना बहुत आसान है, चूंकि चर के संदर्भों में कोई संभावित चक्र नहीं हैं। उदाहरण के लिए, एरलांग में, सभी तर्क और चर ढेर पर आवंटित किए जाते हैं, किन्तु उनके संदर्भ अतिरिक्त रूप से ढेर पर संग्रहीत होते हैं। समारोह के वापस आने के पश्चात्, संदर्भ अभी भी मान्य हैं। वृद्धिशील कचरा संग्राहक द्वारा हीप की सफाई की जाती है।
एमएल में, स्थानीय चर लेक्सिक रूप से स्कॉप्ड होते हैं, और अतः स्टैक-जैसे मॉडल को परिभाषित करते हैं, किन्तु चूंकि वे मूल्यों के लिए बाध्य हैं और वस्तुओं के लिए नहीं, कार्यान्वयन इन मानों को क्लोजर की डेटा संरचना में कॉपी करने के लिए स्वतंत्र है जो कि अदृश्य है प्रोग्रामर।
स्कीम (प्रोग्रामिंग भाषा), जिसमें गतिशील चरों और कचरा संग्रह के साथ ALGOL जैसी शाब्दिक विस्तार सिस्टम है, में स्टैक प्रोग्रामिंग मॉडल का अभाव है और यह स्टैक-आधारित भाषाओं की सीमाओं से ग्रस्त नहीं है। योजना में क्लोजर स्वाभाविक रूप से व्यक्त किए जाते हैं। लैम्ब्डा फॉर्म कोड को संलग्न करता है, और इसके पर्यावरण के मुक्त चर कार्यक्रम के भीतर तब तक बने रहते हैं जब तक उन्हें संभवतः अनुलेख किया जा सकता है, और अतः उन्हें किसी अन्य योजना अभिव्यक्ति के रूप में स्वतंत्र रूप से उपयोग किया जा सकता है।
क्लोजर समवर्ती संगणना के अभिनेता मॉडल में अभिनेताओं से निकटता से संबंधित हैं, जहां समारोह के शाब्दिक वातावरण में मूल्यों को परिचित कहा जाता है। समवर्ती प्रोग्रामिंग भाषाओं में क्लोजर के लिए महत्वपूर्ण मुद्दा यह है कि क्या क्लोजर में चरों को अपडेट किया जा सकता है और यदि हां, तो इन अद्यतन को कैसे समक्रमिक किया जा सकता है। अभिनेता समाधान प्रदान करते हैं।[12]
क्लोजर समारोह ऑब्जेक्ट्स से निकटता से संबंधित हैं; पूर्व से दूसरे में परिवर्तन को निष्क्रियता या लैम्ब्डा उठाना के रूप में जाना जाता है; क्लोजर रूपांतरण भी देखें।
शब्दार्थ में अंतर
शाब्दिक वातावरण
जैसा कि भिन्न-भिन्न भाषाओं में हमेशा शाब्दिक वातावरण की सामान्य परिभाषा नहीं होती है, उनके बंद होने की परिभाषा भी भिन्न हो सकती है। शाब्दिक पर्यावरण की सामान्य रूप से आयोजित न्यूनतम परिभाषा इसे चक्र में बाध्यकारी सभी नामों के सेट के रूप में परिभाषित करती है, और यह भी कि किसी भी भाषा में बंद होने पर कब्जा करना पड़ता है। चूँकि चर (प्रोग्रामिंग) आबद्धिंग का अर्थ भी भिन्न होता है। अनिवार्य भाषाओं में, चर स्मृति में सापेक्ष स्थानों से जुड़ते हैं जो मूल्यों को संग्रहीत कर सकते हैं। चूँकि आबद्धिंग का सापेक्ष स्थान कार्यावधि पर नहीं परिवर्तितता है, किन्तु सीमित स्थिति में मान परिवर्तित सकता है। ऐसी भाषाओं में, चूंकि क्लोजर आबद्धिंग को कैप्चर करता है, चर पर कोई भी ऑपरेशन, चाहे क्लोजर से किया गया हो या नहीं, उसी रिलेटिव मेमोरी स्थिति पर किया जाता है। इसे अधिकांशतः चर को संदर्भ द्वारा कैप्चर करना कहा जाता है। यहां ईसीएमएस्क्रिप्ट में अवधारणा को चित्रित करने वाला उदाहरण दिया गया है, जो ऐसी ही भाषा है:
// जावास्क्रिप्ट वार एफ, जी,
समारोह फू () {
वार एक्स; च = समारोह () {वापसी ++x; }; जी = समारोह () {वापसी --x; }; एक्स = 1; चेतावनी ('फू के अंदर, एफ को कॉल करें):' + एफ ());
}
फू (); // 2
चेतावनी ('जी को कॉल करें):' + जी ()); // 1 (--x)
चेतावनी ('जी को कॉल करें):' + जी ()); // 0 (--x)
चेतावनी ('कॉल टू एफ ():' + एफ ()); // 1 (++x)
चेतावनी ('कॉल टू एफ ():' + एफ ()); // 2 (++x)
समारोह फू
और चरों द्वारा संदर्भित क्लोजर f
और g
सभी स्थानीय चर द्वारा दर्शाए गए समान सापेक्ष स्मृति स्थान का उपयोग करते हैं x
.
कुछ उदाहरणों में उपरोक्त व्यवहार अवांछनीय हो सकता है, और अलग शाब्दिक समापन को बांधना आवश्यक है। फिर से ईसीएमएस्क्रिप्ट में, इसका उपयोग करके किया जाएगा समारोह.bind()
.
=== उदाहरण 1: अनसीमित चर === का संदर्भ[13]
वार मॉड्यूल = {
एक्स: 42, getX: समारोह () {इसे वापस करें। x; }
} var अनसीमितगेटएक्स = मॉड्यूल.गेटएक्स; कंसोल.लॉग (अनसीमितगेटएक्स ()); // समारोह को वैश्विक चक्र में प्रयुक्त किया जाता है // अपरिभाषित उत्सर्जित करता है चूंकि 'x' वैश्विक चक्र में निर्दिष्ट नहीं है।
var सीमितगेटएक्स = अनसीमितगेटएक्स.आबद्ध (मॉड्यूल); // ऑब्जेक्ट मॉड्यूल को क्लोजर के रूप में निर्दिष्ट करें कंसोल.लॉग (सीमितगेटएक्स ()); // 42 का उत्सर्जन करता है </वाक्यविन्यास हाइलाइट>
उदाहरण 2: बाध्य चर के लिए आकस्मिक संदर्भ
इस उदाहरण के लिए अपेक्षित व्यवहार यह होगा कि क्लिक किए जाने पर प्रत्येक लिंक को अपनी आईडी छोड़नी चाहिए; किन्तु चूंकि चर 'ई' उपरोक्त चक्र से जुड़ा हुआ है, और क्लिक पर आलसी मूल्यांकन किया गया है, वास्तव में क्या होता है कि प्रत्येक क्लिक ईवेंट अंतिम तत्व की आईडी को लूप के अंत में बंधे 'तत्व' में उत्सर्जित करता है।[14]
<वाक्यविन्यास लैंग = एक्मास्क्रिप्ट>
var एलिमेंट्स = document.getElementsByTagName ('ए')
// गलत: ई 'फॉर' लूप वाले समारोह के लिए बाध्य है, न कि हैंडल को बंद करने के लिए के लिए (तत्वों का संस्करण) {e.onclick = समारोह हैंडल () {अलर्ट (e.id);}}
यहाँ फिर से परिवर्तनशील e
का उपयोग करके ब्लॉक के चक्र से बंधे होने की आवश्यकता होगी handle.bind(this)
या let
कीवर्ड।
दूसरी ओर, कई कार्यात्मक भाषाएं, जैसे एमएल (प्रोग्रामिंग भाषा), चर को सीधे मानों से बांधती हैं। इस स्थितियों में, चूंकि बार बाध्य होने के पश्चात् चर के मान को परिवर्तितने का कोई विधि नहीं है, राज्य को बंद करने के बीच साझा करने की कोई आवश्यकता नहीं है - वे केवल उसी मान का उपयोग करते हैं। इसे अधिकांशतः चर को मान द्वारा कैप्चर करना कहा जाता है। जावा के स्थानीय और अनाम वर्ग भी इस श्रेणी में आते हैं - उन्हें होने के लिए कैप्चर किए गए स्थानीय चर की आवश्यकता होती है final
, जिसका अर्थ यह भी है कि राज्य को साझा करने की कोई आवश्यकता नहीं है।
कुछ भाषाएँ आपको चर या उसके स्थान के मान को कैप्चर करने के बीच चयन करने में सक्षम बनाती हैं। उदाहरण के लिए, सी ++ 11 में, कैप्चर किए गए चर या तो घोषित किए जाते हैं [&]
, जिसका अर्थ है संदर्भ द्वारा या साथ में कब्जा कर लिया गया [=]
, जिसका अर्थ है मूल्य द्वारा कब्जा कर लिया गया।
फिर भी और सबसेट, आलसी मूल्यांकन कार्यात्मक भाषाएं जैसे हास्केल (प्रोग्रामिंग भाषा), मूल्यों के अतिरिक्त भविष्य की संगणनाओं के परिणामों के लिए चर को बांधती हैं। हास्केल में इस उदाहरण पर विचार करें:
<वाक्यविन्यास लैंग = हैकेल>
-- हास्केल फू :: भिन्नात्मक a => a -> a -> (a -> a) फू x y = (\z -> z + r)
जहां आर = एक्स / वाई
f :: भिन्नात्मक a => a -> a एफ = फू 1 0
मुख्य = प्रिंट (एफ 123) </वाक्यविन्यास हाइलाइट>
का बंधन r
समारोह के भीतर परिभाषित क्लोजर द्वारा कैप्चर किया गया फू
गणना के लिए है (x / y)
—जो इस स्थितियों में शून्य से विभाजन में परिणत होता है। चूँकि, चूंकि यह अभिकलन है जो कैप्चर किया गया है, न कि मान, त्रुटि केवल तभी प्रकट होती है जब क्लोजर का आह्वान किया जाता है, और वास्तव में कैप्चर किए गए आबद्धिंग का उपयोग करने का प्रयास करता है।
जा रहा बंद
फिर भी अधिक अंतर स्वयं को अन्य व्याख्यात्मक रूप से निर्मित निर्माणों के व्यवहार में प्रकट करते हैं, जैसे कि return
, break
और continue
कथन। इस प्रकार के निर्माण, सामान्य रूप से, संलग्न नियंत्रण विवरण (के स्थितियों में) द्वारा स्थापित पलायन निरंतरता को प्रयुक्त करने के संदर्भ में माना जा सकता है break
और continue
, इस प्रकार की व्याख्या के लिए पुनरावर्ती समारोह कॉल के संदर्भ में लूपिंग निर्माणों पर विचार करने की आवश्यकता होती है)। कुछ भाषाओं में, जैसे ईसीएमएस्क्रिप्ट, return
कथन के संबंध में व्याख्यात्मक रूप से आंतरिक रूप से क्लोजर द्वारा स्थापित निरंतरता को संदर्भित करता है- इस प्रकार, ए return
क्लोजर के भीतर उस कोड को नियंत्रण स्थानांतरित करता है जिसने इसे बुलाया था। चूँकि, स्मॉलटॉक में, सतही रूप से समान ऑपरेटर ^
किसी भी हस्तक्षेप करने वाले स्थिर क्लोजर के एस्केप निरंतरता को अनदेखा करते हुए, विधि आमंत्रण के लिए स्थापित एस्केप निरंतरता को आमंत्रित करता है। क्लोजर के कोड के अंत तक पहुंचकर किसी विशेष क्लोजर की एस्केप निरंतरता को केवल स्मॉलटाक में प्रयुक्त किया जा सकता है। ईसीएमएस्क्रिप्ट और स्मॉलटाक में निम्नलिखित उदाहरण अंतर को उजागर करते हैं:
<वाक्यविन्यास लैंग = स्मॉलटॉक>
गपशप
फू
| एक्सएस | xs := #(1 2 3 4). xs करते हैं: [:x | ^ एक्स]। ^ 0
छड़
ट्रांसक्रिप्ट शो: (सेल्फ फू प्रिंटस्ट्रिंग) प्रिंट 1
</वाक्यविन्यास हाइलाइट>
<वाक्यविन्यास लैंग = जावास्क्रिप्ट> // ईसीएमएस्क्रिप्ट समारोह फू () {
वार xs = [1, 2, 3, 4]; xs.forEach (समारोह (x) {वापसी x;}); वापसी 0;
} चेतावनी (फू ()); // प्रिंट 0 </वाक्यविन्यास हाइलाइट>
उपरोक्त कोड स्निपेट्स अलग प्रकार से व्यवहार करेंगे चूंकि स्मॉलटाक ^
ऑपरेटर और जावास्क्रिप्ट return
ऑपरेटर अनुरूप नहीं हैं। ईसीएमएस्क्रिप्ट उदाहरण में, return x
का नया पुनरावृति प्रारंभ करने के लिए आंतरिक समापन को छोड़ देगा forEach
पाश, जबकि स्मालटाक उदाहरण में, ^x
लूप को निरस्त कर देगा और विधि से वापस आ जाएगा फू
.
सामान्य लिस्प निर्माण प्रदान करता है जो उपरोक्त समारोह में से किसी को व्यक्त कर सकता है: लिस्प (return-from फू x)
स्मॉलटाक के रूप में व्यवहार करता है ^x
, जबकि लिस्प (return-from nil x)
जावास्क्रिप्ट के रूप में व्यवहार करता है return x
. अतः, स्मॉलटॉक कैप्चर किए गए एस्केप निरंतरता को उस सीमा तक जीवित रहने के लिए संभव बनाता है जिसमें इसे सफलतापूर्वक प्रयुक्त किया जा सकता है। विचार करना:
<वाक्यविन्यास लैंग = स्मॉलटॉक>
गपशप
फू
^[ :x | ^x]
छड़
| एफ | च�:= स्वयं फू. एफ मान: 123 त्रुटि!
</वाक्यविन्यास हाइलाइट>
जब बंद विधि द्वारा वापस आ गया फू
आह्वान किया जाता है, यह के आह्वान से मान वापस करने का प्रयास करता है फू
जिसने बंद बनाया। चूँकि वह कॉल पहले ही वापस आ चुकी है और स्मॉलटाक विधि मंगलाचरण मॉडल कई रिटर्न की सुविधा के लिए स्पेगेटी ढेर अनुशासन का पालन नहीं करता है, इस ऑपरेशन के परिणामस्वरूप त्रुटि होती है।
कुछ भाषाएँ, जैसे रूबी (प्रोग्रामिंग भाषा), प्रोग्रामर को रास्ता चुनने में सक्षम बनाती हैं return
कब्जा कर लिया है। रूबी में उदाहरण:
<वाक्यविन्यास लैंग = रूबी>
- माणिक
- प्रोक का उपयोग कर बंद करें
डेफ फू
f = Proc.new { फू से अंदर की खरीद से वापसी वापसी} f.call # control फू को यहां छोड़ देता है फू से वापसी
अंत
- लैम्ब्डा का उपयोग करके बंद करें
डेफ बार
f = लैम्ब्डा {लैम्ब्डा से रिटर्न रिटर्न} f.call # नियंत्रण यहां बार नहीं छोड़ता है बार से वापसी वापसी
अंत
पुट फू # प्रिंट फू फ्रॉम इनसाइड प्रो बार डालता है # बार से रिटर्न प्रिंट करता है </वाक्यविन्यास हाइलाइट>
दोनों Proc.new
और लैम्ब्डा
इस उदाहरण में क्लोजर बनाने के तरीके हैं, किन्तु इस प्रकार से बनाए गए क्लोजर के शब्दार्थ इसके संबंध में भिन्न हैं return
कथन।
स्कीम (प्रोग्रामिंग भाषा) में, की परिभाषा और कार्यक्षेत्र return
नियंत्रण कथन स्पष्ट है (और उदाहरण के लिए केवल मनमाने ढंग से 'वापसी' नाम दिया गया है)। निम्नलिखित रूबी नमूने का सीधा अनुवाद है।
<वाक्यविन्यास लैंग = योजना>
- योजना
(कॉल/सीसी कॉल-साथ-वर्तमान-निरंतरता को परिभाषित करें)
(परिभाषित करें (फू)
(कॉल/सीसी (लैम्ब्डा (वापसी) (परिभाषित करें (एफ) (अंदर से फू से वापसी वापसी)) (एफ)�; नियंत्रण यहां फू छोड़ देता है (फू से वापसी वापसी))))
(परिभाषित करें (बार)
(कॉल/सीसी (लैम्ब्डा (वापसी) (परिभाषित करें (एफ) (कॉल/सीसी (लैम्ब्डा (वापसी) (लैम्ब्डा से वापसी)))) (एफ)�; नियंत्रण यहां बार नहीं छोड़ता (बार से वापसी वापसी))))
(प्रदर्शन (फू)); प्रिंट अंदर से फू से वापस आते हैं (नई पंक्ति) (प्रदर्शन (बार)); प्रिंट बार से वापस आते हैं </वाक्यविन्यास हाइलाइट>
क्लोजर-जैसी संरचनाएं
कुछ भाषाओं में विशेषताएं होती हैं जो क्लोजर के व्यवहार का अनुकरण करती हैं। Java, C++, Objective-C, C#, VB.NET, और D जैसी भाषाओं में, ये विशेषताएँ भाषा के वस्तु-उन्मुख प्रतिमान का परिणाम हैं।
कॉलबैक (सी)
कुछ सी (प्रोग्रामिंग भाषा) पुस्तकालय समर्थन करते हैं
कॉलबैक (कंप्यूटर विज्ञान) एस। यह है
कभी-कभी दो मान प्रदान करके कार्यान्वित किया जाता है जब
लाइब्रेरी के साथ कॉलबैक पंजीकृत करना: समारोह
सूचक और अलग void*
के लिए सूचक
उपयोगकर्ता की पसंद का मनमाना डेटा। जब पुस्तकालय
कॉलबैक समारोह निष्पादित करता है, यह डेटा के साथ गुजरता है
सूचक। यह कॉलबैक को राज्य और बनाए रखने में सक्षम बनाता है
उस समय कैप्चर की गई जानकारी को संदर्भित करने के लिए
पुस्तकालय के साथ पंजीकृत। मुहावरा समान है
कार्यक्षमता में बंद, किन्तु सिंटैक्स में नहीं।
void*
de> पॉइंटर प्रकार की सुरक्षा नहीं है अतः यह C
सी #, हास्केल या एमएल में टाइप-सेफ क्लोजर से मुहावरा अलग है।
जीयूआई विजेट टूलकिट में कॉलबैक का व्यापक रूप से उपयोग किया जाता है सामान्य को जोड़कर घटना-संचालित प्रोग्रामिंग प्रयुक्त करें ग्राफिकल विगेट्स के कार्य (मेनू, बटन, चेक बॉक्स, स्लाइडर्स, स्पिनर्स, आदि) एप्लिकेशन-विशिष्ट समारोह के साथ आवेदन के लिए विशिष्ट वांछित व्यवहार को प्रयुक्त करना।
स्थिर समारोह और समारोह पॉइंटर (सी)
जीसीसी विस्तार के साथ, स्थिर समारोह का उपयोग किया जा सकता है और समारोह पॉइंटर क्लोजर का अनुकरण कर सकता है, बशर्ते समारोह युक्त चक्र से बाहर न हो।
निम्न उदाहरण अमान्य है चूंकि adder
शीर्ष-स्तरीय परिभाषा है (संकलक संस्करण के आधार पर, यह अनुकूलन के बिना संकलित होने पर सही परिणाम उत्पन्न कर सकता है, अर्थात -O0
):
<वाक्यविन्यास प्रकाश लैंग = सी>
- सम्मिलित <stdio.h>
टाइपपीफ इंट (*fn_int_to_int)(int); // समारोह का प्रकार int->int
fn_int_to_int योजक (पूर्णांक संख्या) {
इंट ऐड (इंट मान) { रिटर्न मान + नंबर; } वापसी और जोड़ें; // और ऑपरेटर यहाँ वैकल्पिक है चूंकि C में समारोह का नाम पॉइंटर है जो स्वयं की ओर इशारा करता है
}
पूर्णांक मुख्य (शून्य) {
fn_int_to_int add10 = योजक (10); प्रिंटफ (% डी \ n, 10 (1) जोड़ें); वापसी 0;
} </वाक्यविन्यास हाइलाइट>
किन्तु चल रहा है adder
(और, वैकल्पिक रूप से, typedef
) में main
इसे वैध बनाता है:
<वाक्यविन्यास प्रकाश लैंग = सी>
- सम्मिलित <stdio.h>
पूर्णांक मुख्य (शून्य) {
टाइपपीफ इंट (*fn_int_to_int)(int); // समारोह का प्रकार int->int fn_int_to_int योजक (पूर्णांक संख्या) { इंट ऐड (इंट मान) { रिटर्न मान + नंबर; } वापसी जोड़ें; } fn_int_to_int add10 = योजक (10); प्रिंटफ (% डी \ n, 10 (1) जोड़ें); वापसी 0;
} </वाक्यविन्यास हाइलाइट>
यदि इसे क्रियान्वित किया जाता है तो यह अब प्रिंट करता है 11
आशा के अनुसार।
स्थानीय वर्ग और लैम्ब्डा फ़ंक्शंस (जावा)
जावा (प्रोग्रामिंग भाषा) क्लास (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग) को विधि (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग) के अंदर परिभाषित करने में सक्षम बनाता है। इन्हें स्थानीय वर्ग कहा जाता है। जब ऐसी कक्षाओं का नाम नहीं दिया जाता है, तो उन्हें अनाम वर्ग (या अनाम आंतरिक वर्ग) के रूप में जाना जाता है। स्थानीय वर्ग (या तो नामित या अनाम) लेक्सिक रूप से संलग्न कक्षाओं में नामों का उल्लेख कर सकता है, या केवल-पढ़ने के लिए चर (के रूप में चिह्नित) final
) शाब्दिक रूप से संलग्न विधि में।
<वाक्यविन्यास प्रकाश लैंग = जावा> वर्ग गणनाविंडो JFrame का विस्तार करता है {
निजी अस्थिर इंट परिणाम; // ... सार्वजनिक शून्य गणना भिन्न-भिन्न थ्रेड (अंतिम यूआरआई यूरी) { // अभिव्यक्ति नया रननेबल () {...} 'रननेबल' इंटरफ़ेस को प्रयुक्त करने वाला अनाम वर्ग है। नया सूत्र( नया रननेबल () { शून्य रन () { // यह अंतिम स्थानीय चर पढ़ सकता है: गणना (यूरी); // यह संलग्न वर्ग के निजी क्षेत्रों तक पहुँच सकता है: परिणाम = परिणाम + 10; } } )।प्रारंभ करना(); }
} </वाक्यविन्यास हाइलाइट>
का कब्जा final
चरों आपको मान द्वारा चरों को कैप्चर करने में सक्षम बनाता है। यदि आप जिस चर को कैप्चर करना चाहते हैं वह गैर-final
, आप इसे हमेशा अस्थायी में कॉपी कर सकते हैं final
कक्षा से ठीक पहले परिवर्तनशील।
रेफरेंस द्वारा चरों को कैप्चर करने का उपयोग करके अनुकरण किया जा सकता है final
परिवर्तनशील कंटेनर का संदर्भ, उदाहरण के लिए, एकल-तत्व सरणी। स्थानीय वर्ग स्वयं कंटेनर संदर्भ के मूल्य को परिवर्तितने में सक्षम नहीं होगा, किन्तु यह कंटेनर की सामग्री को परिवर्तितने में सक्षम होगा।
जावा 8 के लैम्ब्डा भावों के आगमन के साथ,[15] क्लोजर उपरोक्त कोड को इस प्रकार निष्पादित करने का कारण बनता है:
<वाक्यविन्यास प्रकाश लैंग = जावा> वर्ग गणनाविंडो JFrame का विस्तार करता है {
निजी अस्थिर इंट परिणाम; // ... सार्वजनिक शून्य गणना भिन्न-भिन्न थ्रेड (अंतिम यूआरआई यूरी) { // कोड () -> { /* कोड */} क्लोजर है। नया थ्रेड (() -> { गणना (यूरी); परिणाम = परिणाम + 10; })।प्रारंभ करना(); }
} </वाक्यविन्यास हाइलाइट>
स्थानीय वर्ग प्रकार के आंतरिक वर्ग हैं जो विधि के शरीर के भीतर घोषित किए जाते हैं। जावा आंतरिक कक्षाओं का भी समर्थन करता है जिन्हें संलग्न वर्ग के गैर-स्थैतिक सदस्यों के रूप में घोषित किया जाता है।[16] उन्हें सामान्यतः आंतरिक कक्षाओं के रूप में संदर्भित किया जाता है।[17] इन्हें संलग्न वर्ग के शरीर में परिभाषित किया गया है और संलग्न वर्ग के आवृत्ति चरों तक पूर्ण पहुंच है। इन इंस्टेंस चरों के लिए उनके बंधन के कारण, विशेष सिंटैक्स का उपयोग करके संलग्न वर्ग के उदाहरण के लिए स्पष्ट बंधन के साथ आंतरिक वर्ग को केवल तत्काल किया जा सकता है।[18] <वाक्यविन्यास प्रकाश लैंग = जावा> पब्लिक क्लास संलग्न क्लास {
/ * आंतरिक वर्ग को परिभाषित करें * / पब्लिक क्लास इनरक्लास { सार्वजनिक पूर्णांक वृद्धि और रिटर्न काउंटर () { वापसी काउंटर ++; } }
निजी इंट काउंटर; { काउंटर = 0; }
सार्वजनिक int getCounter () { वापसी काउंटर; }
सार्वजनिक स्थैतिक शून्य main (String [] args) { EnclosingClass enclosingClassInstance = new EnclosingClass(); / * उदाहरण के लिए बाध्यकारी के साथ आंतरिक वर्ग को तुरंत चालू करें */ EnclosingClass.InnerClass innerClassInstance = enclosingClassInstance.new InnerClass();
for (int i = enclosingClassInstance.getCounter(); (i = innerClassInstance.incrementAndReturnCounter ()) <10; /* इंक्रीमेंट चरण छोड़ा गया */) { System.out.println (i); } }
} </वाक्यविन्यास हाइलाइट>
निष्पादन पर, यह 0 से 9 तक के पूर्णांकों को प्रिंट करेगा। इस प्रकार के वर्ग को स्थिर वर्ग के साथ भ्रमित न करने के लिए सावधान रहें, जो उसी प्रकार से घोषित किया जाता है जैसे स्थैतिक संशोधक के उपयोग के साथ; उनका वांछित प्रभाव नहीं है, बल्कि केवल वे वर्ग हैं जिनके समीप संलग्न वर्ग में परिभाषित कोई विशेष बंधन नहीं है।
जावा संस्करण इतिहास#Java_8 के रूप में, जावा प्रथम श्रेणी की वस्तुओं के रूप में समारोह का समर्थन करता है। इस रूप के लैम्ब्डा भावों को प्रकार का माना जाता है समारोह<T,U>
जहां T डोमेन है और U छवि प्रकार है। इसके साथ व्यंजक कहा जा सकता है .apply(T t)
विधि, किन्तु मानक विधि कॉल के साथ नहीं।
<वाक्यविन्यास प्रकाश लैंग = जावा> सार्वजनिक स्थैतिक शून्य main (String [] args) {
समारोह <स्ट्रिंग, पूर्णांक> लंबाई = s -> s.length ();
System.out.println (लंबाई। प्रयुक्त करें (हैलो, दुनिया!)); // 13 प्रिंट करेगा।
} </वाक्यविन्यास हाइलाइट>
ब्लॉक (सी, सी ++, ऑब्जेक्टिव-सी 2.0)
Apple Inc. ने C (प्रोग्रामिंग भाषा), C++, ऑब्जेक्टिव-C 2.0 और Mac OS X स्नो लेपर्ड | Mac OS X 10.6 स्नो लेपर्ड और IOS ( सेब) | आईओएस 4.0। ऐप्पल ने जीसीसी और क्लैंग कंपाइलर्स के लिए अपना कार्यान्वयन उपलब्ध कराया।
शाब्दिक ब्लॉक और ब्लॉक करने के लिए पॉइंटर्स को चिह्नित किया गया है ^
. जब ब्लॉक बनाया जाता है तो सामान्य स्थानीय चर मूल्य द्वारा कब्जा कर लिया जाता है, और केवल पढ़ने के लिए ब्लॉक के अंदर होता है। संदर्भ द्वारा कैप्चर किए जाने वाले चरों को चिह्नित किया गया है __block
. जिन ब्लॉकों को उनके द्वारा बनाए गए चक्र से बाहर बने रहने की आवश्यकता है, उन्हें कॉपी करने की आवश्यकता हो सकती है।[19][20]
<वाक्यविन्यास हाइलाइट लैंग = ओबीजेसी>
टाइपपीफ इंट (^ इंटब्लॉक) ();
इंटब्लॉक डाउनकाउंटर (इंट स्टार्ट) { __ ब्लॉक इंट आई = स्टार्ट; वापसी ^ इंट () { वापसी मैं--; } कॉपी] ऑटोरिलीज]; }
इंटब्लॉक एफ = डाउनकाउंटर (5); एनएसएलओजी (@% डी, एफ ()); एनएसएलओजी (@% डी, एफ ()); एनएसएलओजी (@% डी, एफ ()); </वाक्यविन्यास हाइलाइट>
प्रतिनिधि (सी #, वीबी.नेट, डी)
सी शार्प (प्रोग्रामिंग भाषा) | सी # अनाम तरीके और लैम्ब्डा अभिव्यक्ति क्लोजर का समर्थन करते हैं:
<वाक्यविन्यास प्रकाश लैंग = csharp> var डेटा = नया [] {1, 2, 3, 4}; वार गुणक = 2; var परिणाम = डेटा। चयन करें (x => x * गुणक); </वाक्यविन्यास हाइलाइट>
Visual Basic .NET, जिसमें C# के समान कई भाषा सुविधाएँ हैं, क्लोजर के साथ लैम्ब्डा अभिव्यक्ति का भी समर्थन करता है:
<वाक्यविन्यास लैंग = vb.net> मंद डेटा = {1, 2, 3, 4} मंद गुणक = 2 मंद परिणाम = डेटा। चयन करें (समारोह (x) x * गुणक) </वाक्यविन्यास हाइलाइट>
डी (प्रोग्रामिंग भाषा) में, क्लोजर को डेलीगेट्स द्वारा प्रयुक्त किया जाता है, फंक्शन पॉइंटर को कॉन्टेक्स्ट पॉइंटर के साथ जोड़ा जाता है (उदाहरण के लिए क्लास इंस्टेंस, या क्लोजर के स्थितियों में हीप पर स्टैक फ्रेम)।
<वाक्यविन्यास प्रकाश लैंग = डी> ऑटो टेस्ट 1 () {
इंट ए = 7; वापसी प्रतिनिधि () {वापसी + 3; }; // अनाम प्रतिनिधि निर्माण
}
ऑटो टेस्ट 2 () {
इंट ए = 20; इंट फू () {वापसी ए + 5; } // आंतरिक कार्य वापसी और फू; // प्रतिनिधि बनाने का दूसरा विधि
}
शून्य बार () {
ऑटो डीजी = test1 (); डीजी (); // = 10 // ठीक है, test1.a क्लोजर में है और अभी भी उपस्तिथ है
डीजी = test2 (); डीजी (); // = 25 // ठीक है, test2.a बंद होने की स्थिति में है और अभी भी उपस्तिथ है
} </वाक्यविन्यास हाइलाइट>
D संस्करण 1 में सीमित क्लोजर समर्थन है। उदाहरण के लिए, उपरोक्त कोड सही ढंग से काम नहीं करेगा, चूंकि चर a स्टैक पर है, और परीक्षण () से लौटने के पश्चात्, यह अब इसका उपयोग करने के लिए मान्य नहीं है (संभवतः डीजी () के माध्यम से फू को कॉल करना, 'वापसी करेगा यादृच्छिक 'पूर्णांक)। इसे ढेर पर चर 'ए' को स्पष्ट रूप से आवंटित करके, या सभी आवश्यक बंद चरों को संग्रहीत करने के लिए स्ट्रक्चर्स या क्लास का उपयोग करके हल किया जा सकता है और उसी कोड को प्रयुक्त करने वाली विधि से प्रतिनिधि का निर्माण किया जा सकता है। क्लोजर को अन्य समारोह में पारित किया जा सकता है, जब तक कि वे केवल तब तक उपयोग किए जाते हैं जब संदर्भित मान अभी भी मान्य होते हैं (उदाहरण के लिए कॉलबैक पैरामीटर के रूप में क्लोजर के साथ किसी अन्य समारोह को कॉल करना), और सामान्य डेटा प्रोसेसिंग कोड लिखने के लिए उपयोगी होते हैं, अतः यह सीमा , व्यवहार में, अधिकांशतः कोई समस्या नहीं होती है।
यह सीमा डी संस्करण 2 में तय की गई थी - चर 'ए' स्वचालित रूप से हीप पर आवंटित किया जाएगा चूंकि इसका उपयोग आंतरिक समारोह में किया जाता है, और उस समारोह का प्रतिनिधि वर्तमान चक्र से बच सकता है (डीजी या वापसी के लिए नियुक्त मेंट के माध्यम से)। कोई भी अन्य स्थानीय चर (या तर्क) जो प्रतिनिधियों द्वारा संदर्भित नहीं हैं या जो केवल प्रतिनिधियों द्वारा संदर्भित हैं जो वर्तमान चक्र से बाहर नहीं निकलते हैं, स्टैक पर बने रहते हैं, जो हीप आवंटन की तुलना में सरल और तेज़ है। आंतरिक वर्ग विधियों के लिए भी यही सच है जो किसी समारोह के चर को संदर्भित करता है।
समारोह ऑब्जेक्ट्स (सी ++)
सी ++ ओवरलोडिंग द्वारा फ़ंक्शन ऑब्जेक्ट्स को परिभाषित करने में सक्षम बनाता है operator()
. ये ऑब्जेक्ट कुछ हद तक कार्यात्मक प्रोग्रामिंग भाषा में कार्यों की तरह व्यवहार करते हैं। वे रनटाइम पर बनाए जा सकते हैं और इसमें राज्य शामिल हो सकते हैं, लेकिन वे स्थानीय चर को बंद करने के रूप में निहित रूप से कैप्चर नहीं करते हैं। सी ++ 11 के अनुसार, सी ++ भाषा भी क्लोजर का समर्थन करती है, जो एक प्रकार का फ़ंक्शन ऑब्जेक्ट है जो लैम्ब्डा-एक्सप्रेशन नामक एक विशेष भाषा निर्माण से स्वचालित रूप से निर्मित होता है। एक सी ++ क्लोजर क्लोजर ऑब्जेक्ट या संदर्भ के सदस्यों के रूप में एक्सेस किए गए चर की प्रतियों को संग्रहीत करके इसके संदर्भ को कैप्चर कर सकता है। बाद के मामले में, यदि क्लोजर ऑब्जेक्ट संदर्भित ऑब्जेक्ट के दायरे से बाहर निकलता है, तो इसका आह्वान करता है operator()
अपरिभाषित व्यवहार का कारण बनता है क्योंकि सी ++ क्लोजर उनके संदर्भ के जीवनकाल का विस्तार नहीं करते हैं।
<वाक्यविन्यास लैंग = सीपीपी> शून्य फू (स्ट्रिंग मायनाम) {
इंट वाई; वेक्टर <स्ट्रिंग> एन; // ... ऑटो मैं = एसटीडी::find_if(n.begin(), n.end(), // यह लैम्ब्डा अभिव्यक्ति है: [&] (स्थिरांक स्ट्रिंग और s) {वापसी s! = myname && s.size ()> y; } ); // 'i' अब या तो 'n.end ()' है या 'n' में पहले स्ट्रिंग को इंगित करता है // जो 'myname' के बराबर नहीं है और जिसकी लंबाई 'y' से अधिक है
} </वाक्यविन्यास हाइलाइट>
इनलाइन एजेंट (एफिल)
एफिल (प्रोग्रामिंग भाषा) में क्लोजर को परिभाषित करने वाले इनलाइन एजेंट सम्मिलित हैं। इनलाइन एजेंट रूटीन का प्रतिनिधित्व करने वाली वस्तु है, जिसे रूटीन इन-लाइन का कोड देकर परिभाषित किया जाता है। उदाहरण के लिए, में
<वाक्यविन्यास लैंग = एफिल> ok_button.click_event.subscribe ( एजेंट (x, y: INTEGER) करते हैं map.country_at_coordinates (x, y).प्रदर्शन अंत ) </वाक्यविन्यास हाइलाइट>
को तर्क subscribe
एजेंट है, जो दो तर्कों के साथ प्रक्रिया का प्रतिनिधित्व करता है; प्रक्रिया देश को संबंधित निर्देशांक पर ढूंढती है और इसे प्रदर्शित करती है। पूरे एजेंट को ईवेंट प्रकार की सदस्यता दी गई है click_event
के लिए
निश्चित बटन, जिससे कि जब भी उस बटन पर घटना प्रकार का उदाहरण हो - चूंकि उपयोगकर्ता ने बटन पर क्लिक किया है - प्रक्रिया को माउस निर्देशांक के साथ तर्क के रूप में पारित किया जाएगा x
और y
.
एफिल एजेंटों की मुख्य सीमा, जो उन्हें अन्य भाषाओं में बंद होने से अलग करती है, यह है कि वे स्थानीय चर को संलग्न चक्र से संदर्भित नहीं कर सकते हैं। यह डिज़ाइन निर्णय अस्पष्टता से बचने में मदद करता है जब क्लोजर में स्थानीय चर मान के बारे में बात की जाती है - क्या यह चर का नवीनतम मान होना चाहिए या एजेंट के बनाए जाने पर कैप्चर किया गया मान होना चाहिए? केवल Current
(वर्तमान वस्तु का संदर्भ, के अनुरूप this
जावा में), इसकी विशेषताओं और एजेंट के तर्कों को एजेंट निकाय के भीतर से ही अनुलेख किया जा सकता है। एजेंट को अतिरिक्त बंद ऑपरेंड प्रदान करके बाहरी स्थानीय चर के मान पारित किए जा सकते हैं।
सी ++ बिल्डर क्लोजर आरक्षित शब्द
Embarcadero C++ Builder समारोह पॉइंटर के समान सिंटैक्स वाली विधि को पॉइंटर प्रदान करने के लिए आरक्षित शब्द _ क्लोजर प्रदान करता है।[21]
मानक C में आप a लिख सकते हैं typedef निम्नलिखित सिंटैक्स का उपयोग करके समारोह प्रकार के सूचक के लिए:
टाइपपीफ शून्य (*TMyFunctionPointer) (शून्य);
इसी प्रकार से आप घोषित कर सकते हैं a typedef निम्नलिखित सिंटैक्स का उपयोग करने वाली विधि के लिए सूचक के लिए:<syntaxhighlight lang= c++ >
टाइपपीफ शून्य (__closure *TMyMethodPointer) (); </वाक्यविन्यास हाइलाइट>
यह भी देखें
- बेनामी समारोह
- ब्लॉक (सी भाषा विस्तार)
- कमांड पैटर्न
- जारी
- करी
- फंगस की समस्या
- लैम्ब्डा कैलकुलस
- आलसी मूल्यांकन
- आंशिक आवेदन
- स्पेगेटी स्टैक
- सिंटैक्टिक क्लोजर
- मूल्य-स्तरीय प्रोग्रामिंग
टिप्पणियाँ
- ↑ These names most frequently refer to values, mutable variables, or functions, but can also be other entities such as constants, types, classes, or labels.
संदर्भ
- ↑ Sussman and Steele. "Scheme: An interpreter for extended lambda calculus". "... a data structure containing a lambda expression, and an environment to be used when that lambda expression is applied to arguments." (Wikisource)
- ↑ David A. Turner (2012). "Some History of Functional Programming Languages". Trends in Functional Programming '12. Section 2, note 8 contains the claim about M-expressions.
- ↑ P. J. Landin (1964), The mechanical evaluation of expressions
- ↑ Joel Moses (June 1970), The Function of FUNCTION in LISP, or Why the FUNARG Problem Should Be Called the Environment Problem, hdl:1721.1/5854, AI Memo 199,
A useful metaphor for the difference between FUNCTION and QUOTE in LISP is to think of QUOTE as a porous or an open covering of the function since free variables escape to the current environment. FUNCTION acts as a closed or nonporous covering (hence the term "closure" used by Landin). Thus we talk of "open" Lambda expressions (functions in LISP are usually Lambda expressions) and "closed" Lambda expressions. [...] My interest in the environment problem began while Landin, who had a deep understanding of the problem, visited MIT during 1966–67. I then realized the correspondence between the FUNARG lists which are the results of the evaluation of "closed" Lambda expressions in LISP and ISWIM's Lambda Closures.
- ↑ Åke Wikström (1987). Functional Programming using Standard ML. ISBN 0-13-331968-7.
The reason it is called a "closure" is that an expression containing free variables is called an "open" expression, and by associating to it the bindings of its free variables, you close it.
- ↑ Gerald Jay Sussman and Guy L. Steele, Jr. (December 1975), Scheme: An Interpreter for the Extended Lambda Calculus, AI Memo 349
- ↑ Abelson, Harold; Sussman, Gerald Jay; Sussman, Julie (1996). Structure and Interpretation of Computer Programs. Cambridge, MA: MIT Press. p. 98–99. ISBN 0262510871.
- ↑ "array.filter". Mozilla Developer Center. 10 January 2010. Retrieved 2010-02-09.
- ↑ "Re: FP, OO and relations. Does anyone trump the others?". 29 December 1999. Archived from the original on 26 December 2008. Retrieved 2008-12-23.
- ↑ Lambda Expressions and Closures C++ Standards Committee. 29 February 2008.
- ↑ GCC Manual, 6.4 Nested Functions, "If you try to call the nested function through its address after the containing function exits, all hell breaks loose. If you try to call it after a containing scope level exits, and if it refers to some of the variables that are no longer in scope, you may be lucky, but it's not wise to take the risk. If, however, the nested function does not refer to anything that has gone out of scope, you should be safe."
- ↑ Foundations of Actor Semantics Will Clinger. MIT Mathematics Doctoral Dissertation. June 1981.
- ↑ "Function.prototype.bind()". MDN Web Docs. Retrieved 20 November 2018.
- ↑ "Closures". MDN Web Docs. Retrieved 20 November 2018.
- ↑ "Lambda Expressions (The Java Tutorials)".
- ↑ "Nested, Inner, Member, and Top-Level Classes".
- ↑ "Inner Class Example (The Java Tutorials > Learning the Java Language > Classes and Objects)".
- ↑ "Nested Classes (The Java Tutorials > Learning the Java Language > Classes and Objects)".
- ↑ Apple Inc. "Blocks Programming Topics". Retrieved 2011-03-08.
- ↑ Joachim Bengtsson (7 July 2010). "Programming with C Blocks on Apple Devices". Archived from the original on 25 October 2010. Retrieved 2010-09-18.
- ↑ Full documentation can be found at http://docwiki.embarcadero.com/RADStudio/Rio/en/Closure
बाहरी संबंध
- Original "लैम्ब्डा Papers": A classic series of papers by Guy Steele and Gerald Sussman discussing, among other things, the versatility of closures in the context of Scheme (where they appear as लैम्ब्डा expressions).
- Neal Gafter (2007-01-28). "A Definition of Closures".
- Gilad Bracha, Neal Gafter, James Gosling, Peter von der Ahé. "Closures for the Java Programming Language (v0.5)".
{{cite web}}
: CS1 maint: multiple names: authors list (link) - Closures: An article about closures in dynamically typed imperative languages, by Martin Fowler.
- Collection closure methods: An example of a technical domain where using closures is convenient, by Martin Fowler.