क्लोजर (कंप्यूटर प्रोग्रामिंग): Difference between revisions
(Created page with "{{Short description|Technique for creating lexically scoped first class functions}} {{other uses|Closure (mathematics)|Closure (disambiguation)}} {{distinguish|text=the progra...") |
No edit summary |
||
Line 1: | Line 1: | ||
{{Short description|Technique for creating lexically scoped first class functions}} | {{Short description|Technique for creating lexically scoped first class functions}} | ||
{{other uses| | {{other uses|समापन (गणित)|बंद (बहुविकल्पी)}} | ||
{{distinguish|text= | {{distinguish|text=प्रोग्रामिंग भाषा [[क्लोजर]]}} | ||
[[प्रोग्रामिंग भाषा]]ओं में, क्लोजर, लेक्सिकल क्लोजर या फंक्शन क्लोजर भी, प्रथम श्रेणी के कार्यों के साथ भाषा में [[लेक्सिकली स्कोप्ड]] [[नाम बंधन]] को लागू करने की तकनीक है। [[परिचालन शब्दार्थ]], क्लोजर [[रिकॉर्ड (कंप्यूटर विज्ञान)]] है जो [[समारोह (कंप्यूटर विज्ञान)]] को स्टोर करता है{{efn|The function may be stored as a [[reference (computer science)|reference]] to a function, such as a [[function pointer]].}} साथ पर्यावरण के साथ।<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.}} सादे फ़ंक्शन के विपरीत, क्लोजर फ़ंक्शन को उन कैप्चर किए गए चरों को उनके मूल्यों या संदर्भों की क्लोजर प्रतियों के माध्यम से एक्सेस करने की अनुमति देता है, तब भी जब फ़ंक्शन को उनके दायरे से बाहर बुलाया जाता है। | |||
== इतिहास और व्युत्पत्त == | |||
क्लोजर की अवधारणा को 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 में टर्म क्लोजर को पर्यावरण भाग और नियंत्रण भाग के रूप में परिभाषित किया, जैसा कि अभिव्यक्ति के मूल्यांकन के लिए उनकी SECD मशीन द्वारा उपयोग किया जाता है।<ref name=landin>{{citation | |||
| author = P. J. Landin | year = 1964 | title = The mechanical evaluation of expressions | author-link = Peter J. Landin }}</ref> [[जोएल मूसा]] लैंडिन को क्लोजर शब्द की शुरुआत करने का श्रेय देते हैं, जो बेनामी फ़ंक्शन को संदर्भित करता है, जिसके ओपन बाइंडिंग (फ्री वेरिएबल्स) को लेक्सिकल वातावरण द्वारा (या बाउंड इन) बंद कर दिया गया है, जिसके परिणामस्वरूप क्लोज्ड एक्सप्रेशन या क्लोजर होता है।<ref>{{citation | |||
| author = Joel Moses |date=June 1970 | title = The Function of FUNCTION in LISP, or Why the FUNARG Problem Should Be Called the Environment Problem | id = [[AI Memo]] 199| quote = 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 1.5|LISP]] and [[ISWIM]]'s Lambda Closures.|hdl=1721.1/5854 |author-link=Joel Moses }}</ref><ref>{{cite book| author = Åke Wikström| year = 1987| title = Functional Programming using Standard ML| isbn = 0-13-331968-7| quote = 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.| author-link = Åke Wikström}}</ref> इस प्रयोग को बाद में [[गेराल्ड जे सुस्मान]] और गाइ एल. स्टील, जूनियर द्वारा अपनाया गया, जब उन्होंने 1975 में स्कीम (प्रोग्रामिंग भाषा) को परिभाषित किया,<ref>{{citation| author = [[Gerald Jay Sussman]] and [[Guy L. Steele, Jr.]]|date=December 1975| title = Scheme: An Interpreter for the Extended Lambda Calculus| id = [[AI Memo]] 349}}</ref> [[लिस्प (प्रोग्रामिंग भाषा)]] का लेक्सिकली स्कोप्ड वेरिएंट, और व्यापक हो गया। | |||
सुस्मान और [[हेरोल्ड एबेलसन]] भी 1980 के दशक में दूसरे, असंबंधित अर्थ के साथ क्लोजर शब्द का उपयोग करते हैं: ऑपरेटर की संपत्ति जो [[डेटा संरचना]] में डेटा जोड़ती है और नेस्टेड डेटा संरचनाओं को भी जोड़ने में सक्षम होती है। शब्द का यह उपयोग कंप्यूटर विज्ञान में पूर्व उपयोग के अतिरिक्त क्लोजर (गणित) से आता है। लेखक इस ओवरलैप को शब्दावली में दुर्भाग्यपूर्ण मानते हैं।<ref>{{cite book |last1=Abelson |first1=Harold |last2=Sussman |first2=Gerald Jay |last3=Sussman |first3=Julie |date=1996 |title=Structure and Interpretation of Computer Programs |url=https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book.html |location=Cambridge, MA |publisher=MIT Press |page=98–99 |isbn=0262510871}}</ref> | |||
== अनाम कार्य == | |||
{{further|अनाम समारोह}} | |||
क्लोजर शब्द का प्रयोग अधिकांशतः अज्ञात फ़ंक्शन के पर्याय के रूप में किया जाता है, चूंकि सख्ती से, अनाम फ़ंक्शन फ़ंक्शन [[शाब्दिक (कंप्यूटर प्रोग्रामिंग)]] है, जिसका कोई नाम नहीं है, जबकि क्लोजर फ़ंक्शन का उदाहरण है, मान (कंप्यूटर विज्ञान), जिसका गैर -स्थानीय चर या तो मूल्यों या [[चर (कंप्यूटर विज्ञान)]] के लिए बाध्य हैं (भाषा के आधार पर; नीचे #Lexical पर्यावरण अनुभाग देखें)। | |||
क्लोजर शब्द का प्रयोग | |||
उदाहरण के लिए, निम्नलिखित [[पायथन (प्रोग्रामिंग भाषा)]] कोड में: | उदाहरण के लिए, निम्नलिखित [[पायथन (प्रोग्रामिंग भाषा)]] कोड में: | ||
<वाक्यविन्यास लैंग = अजगर> | <वाक्यविन्यास लैंग = अजगर> | ||
डेफ एफ (एक्स): | डेफ एफ (एक्स): | ||
डेफ जी (वाई): | |||
रिटर्न एक्स + वाई | |||
रिटर्न जी # रिटर्न क्लोजर। | |||
डीईएफ़ एच (एक्स): | डीईएफ़ एच (एक्स): | ||
रिटर्न लैम्ब्डा वाई: एक्स + वाई # क्लोजर लौटाएं। | |||
# वेरिएबल्स को विशिष्ट क्लोजर असाइन करना। | # वेरिएबल्स को विशिष्ट क्लोजर असाइन करना। | ||
Line 40: | Line 39: | ||
जोर एच (1) (5) == 6 # एच (1) बंद है। | जोर एच (1) (5) == 6 # एच (1) बंद है। | ||
</वाक्यविन्यास हाइलाइट> | </वाक्यविन्यास हाइलाइट> | ||
के मूल्य <code>a</code> और <code>b</code> क्लोजर हैं, दोनों | के मूल्य <code>a</code> और <code>b</code> क्लोजर हैं, दोनों स्थितियों में नेस्टेड फ़ंक्शन को एन्क्लोजिंग फ़ंक्शन से मुक्त चर के साथ लौटाकर उत्पादित किया जाता है, जिससे कि मुक्त चर पैरामीटर के मान से जुड़ा हो <code>x</code> संलग्न समारोह का। में बंद हैं <code>a</code> और <code>b</code> कार्यात्मक रूप से समान हैं। कार्यान्वयन में एकमात्र अंतर यह है कि पहले स्थितियों में हमने नेस्टेड फ़ंक्शन का उपयोग नाम के साथ किया था, <code>g</code>, जबकि दूसरे स्थितियों में हमने अनाम नेस्टेड फ़ंक्शन (Python कीवर्ड का उपयोग करके) का उपयोग किया <code>lambda</code> अज्ञात फ़ंक्शन बनाने के लिए)। उन्हें परिभाषित करने में प्रयुक्त मूल नाम, यदि कोई हो, अप्रासंगिक है। | ||
क्लोजर किसी भी अन्य वैल्यू की तरह | क्लोजर किसी भी अन्य वैल्यू की तरह वैल्यू है। इसे वेरिएबल को असाइन करने की आवश्यकता नहीं है और इसके अतिरिक्त इसे सीधे उपयोग किया जा सकता है, जैसा कि उदाहरण की अंतिम दो पंक्तियों में दिखाया गया है। इस उपयोग को अनाम क्लोजर माना जा सकता है। | ||
नेस्टेड फ़ंक्शन परिभाषाएं स्वयं क्लोजर नहीं हैं: उनके पास | नेस्टेड फ़ंक्शन परिभाषाएं स्वयं क्लोजर नहीं हैं: उनके पास फ्री वेरिएबल है जो अभी तक बाध्य नहीं है। केवल बार एनक्लोजिंग फ़ंक्शन का मूल्यांकन पैरामीटर के मान के साथ किया जाता है, नेस्टेड फ़ंक्शन बाउंड का फ्री वेरिएबल होता है, जो क्लोजर बनाता है, जिसे बाद में एनक्लोजिंग फ़ंक्शन से लौटाया जाता है। | ||
अंत में, गैर-स्थानीय चर के दायरे से बाहर होने पर | अंत में, गैर-स्थानीय चर के दायरे से बाहर होने पर क्लोजर केवल मुक्त चर वाले फ़ंक्शन से अलग होता है, अन्यथा परिभाषित वातावरण और निष्पादन वातावरण मेल खाते हैं और इन्हें अलग करने के लिए कुछ भी नहीं है (स्थैतिक और गतिशील बाध्यकारी को अलग नहीं किया जा सकता है क्योंकि नाम समान मानों को हल करते हैं)। उदाहरण के लिए, नीचे दिए गए प्रोग्राम में, फ्री वेरिएबल के साथ कार्य करता है <code>x</code> (गैर-स्थानीय चर के लिए बाध्य <code>x</code> वैश्विक दायरे के साथ) उसी वातावरण में क्रियान्वित किए जाते हैं जहाँ <code>x</code> परिभाषित किया गया है, इसलिए यह सारहीन है कि क्या ये वास्तव में बंद हैं: | ||
<वाक्यविन्यास लैंग = अजगर> | <वाक्यविन्यास लैंग = अजगर> | ||
एक्स = 1 | एक्स = 1 | ||
Line 52: | Line 51: | ||
डेफ एफ (वाई): | डेफ एफ (वाई): | ||
रिटर्न एक्स + वाई | |||
नक्शा (एफ, अंक) | नक्शा (एफ, अंक) | ||
नक्शा (लैम्ब्डा वाई: एक्स + वाई, अंक) | नक्शा (लैम्ब्डा वाई: एक्स + वाई, अंक) | ||
</वाक्यविन्यास हाइलाइट> | </वाक्यविन्यास हाइलाइट> | ||
यह | यह अधिकांशतः फ़ंक्शन रिटर्न द्वारा हासिल किया जाता है, क्योंकि फ़ंक्शन को गैर-स्थानीय चर के दायरे में परिभाषित किया जाना चाहिए, इस स्थितियों में सामान्यतः इसका दायरा छोटा होगा। | ||
यह [[चर छायांकन]] (जो गैर-स्थानीय चर के दायरे को कम करता है) द्वारा भी प्राप्त किया जा सकता है, | यह [[चर छायांकन]] (जो गैर-स्थानीय चर के दायरे को कम करता है) द्वारा भी प्राप्त किया जा सकता है, चूंकि व्यवहार में यह कम आम है, क्योंकि यह कम उपयोगी है और शैडोइंग को हतोत्साहित किया जाता है। इस उदाहरण में <code>f</code> बंद होने के रूप में देखा जा सकता है क्योंकि <code>x</code> के शरीर में <code>f</code> के लिए बाध्य है <code>x</code> वैश्विक नामस्थान में, नहीं <code>x</code> स्थानीय के लिए <code>g</code>: | ||
<वाक्यविन्यास लैंग = अजगर> | <वाक्यविन्यास लैंग = अजगर> | ||
एक्स = 0 | एक्स = 0 | ||
डेफ एफ (वाई): | डेफ एफ (वाई): | ||
रिटर्न एक्स + वाई | |||
डेफ जी (जेड): | डेफ जी (जेड): | ||
x = 1 # स्थानीय x छाया वैश्विक x | |||
रिटर्न एफ (जेड) | |||
g(1) # 1 का मूल्यांकन करता है, 2 का नहीं | g(1) # 1 का मूल्यांकन करता है, 2 का नहीं | ||
Line 74: | Line 73: | ||
== अनुप्रयोग == | == अनुप्रयोग == | ||
क्लोजर का उपयोग उन भाषाओं से जुड़ा हुआ है जहां कार्य [[प्रथम श्रेणी की वस्तु]]एं हैं, जिसमें उच्च-क्रम के कार्यों के परिणाम के रूप में कार्यों को वापस किया जा सकता है, या अन्य फ़ंक्शन कॉलों के लिए तर्क के रूप में पारित किया जा सकता है; यदि मुक्त चर वाले कार्य प्रथम श्रेणी के हैं, तो वापस लौटने से | क्लोजर का उपयोग उन भाषाओं से जुड़ा हुआ है जहां कार्य [[प्रथम श्रेणी की वस्तु]]एं हैं, जिसमें उच्च-क्रम के कार्यों के परिणाम के रूप में कार्यों को वापस किया जा सकता है, या अन्य फ़ंक्शन कॉलों के लिए तर्क के रूप में पारित किया जा सकता है; यदि मुक्त चर वाले कार्य प्रथम श्रेणी के हैं, तो वापस लौटने से बंद हो जाता है। इसमें [[कार्यात्मक प्रोग्रामिंग भाषाएं]] जैसे लिस्प (प्रोग्रामिंग भाषा) और [[एमएल (प्रोग्रामिंग भाषा)]], साथ ही साथ कई आधुनिक, बहु-प्रतिमान भाषाएं सम्मिलित हैं, जैसे | ||
[[जूलिया (प्रोग्रामिंग भाषा)]], | [[जूलिया (प्रोग्रामिंग भाषा)]], | ||
पायथन (प्रोग्रामिंग भाषा) और | पायथन (प्रोग्रामिंग भाषा) और | ||
[[जंग (प्रोग्रामिंग भाषा)]]। | [[जंग (प्रोग्रामिंग भाषा)]]। | ||
[[कॉलबैक (कंप्यूटर प्रोग्रामिंग)]] के साथ क्लोजर का भी | [[कॉलबैक (कंप्यूटर प्रोग्रामिंग)]] के साथ क्लोजर का भी अधिकांशतः उपयोग किया जाता है, विशेष रूप से [[आयोजन प्रबंधकर्ता]] के लिए, जैसे कि [[जावास्क्रिप्ट]] में, जहां उनका उपयोग [[गतिशील वेब पेज]] के साथ बातचीत के लिए किया जाता है। | ||
सूचनाओं को छिपाने के लिए क्लोजर का उपयोग [[निरंतरता-गुजरने वाली शैली]] में भी किया जा सकता है। [[वस्तु (कंप्यूटर विज्ञान)]] और [[नियंत्रण संरचना]]ओं जैसे निर्माण इस प्रकार बंद होने के साथ लागू किए जा सकते हैं। कुछ भाषाओं में, | सूचनाओं को छिपाने के लिए क्लोजर का उपयोग [[निरंतरता-गुजरने वाली शैली]] में भी किया जा सकता है। [[वस्तु (कंप्यूटर विज्ञान)]] और [[नियंत्रण संरचना]]ओं जैसे निर्माण इस प्रकार बंद होने के साथ लागू किए जा सकते हैं। कुछ भाषाओं में, क्लोजर तब हो सकता है जब फ़ंक्शन को दूसरे फ़ंक्शन के भीतर परिभाषित किया जाता है, और आंतरिक फ़ंक्शन बाहरी फ़ंक्शन के स्थानीय चर को संदर्भित करता है। रन टाइम (प्रोग्राम जीवनचक्र चरण) | रन-टाइम पर, जब बाहरी फ़ंक्शन निष्पादित होता है, तो क्लोजर बनता है, जिसमें आंतरिक फ़ंक्शन का कोड होता है और क्लोजर के लिए आवश्यक बाहरी फ़ंक्शन के किसी भी चर के संदर्भ (अपवैल्यू) होते हैं। | ||
=== प्रथम श्रेणी के कार्य === | === प्रथम श्रेणी के कार्य === | ||
{{further| | {{further|प्रथम श्रेणी समारोह}} | ||
क्लोजर | |||
क्लोजर सामान्यतः प्रथम श्रेणी के ऑब्जेक्ट वाली भाषाओं में दिखाई देते हैं। प्रथम श्रेणी के कार्य-दूसरे शब्दों में, ऐसी भाषाएं फ़ंक्शन को तर्कों के रूप में पारित करने में सक्षम बनाती हैं, फ़ंक्शन कॉल से वापस आती हैं, चर नामों से बंधी होती हैं, आदि, सरल प्रकार जैसे स्ट्रिंग्स की तरह और पूर्णांक। उदाहरण के लिए, निम्नलिखित योजना (प्रोग्रामिंग भाषा) फ़ंक्शन पर विचार करें: | |||
<वाक्यविन्यास लैंग = योजना> | <वाक्यविन्यास लैंग = योजना> | ||
; बेची गई कम से कम थ्रेशोल्ड प्रतियों वाली सभी पुस्तकों की सूची लौटाएं। | ; बेची गई कम से कम थ्रेशोल्ड प्रतियों वाली सभी पुस्तकों की सूची लौटाएं। | ||
(परिभाषित करें (सर्वाधिक बिकने वाली पुस्तकों की सीमा) | (परिभाषित करें (सर्वाधिक बिकने वाली पुस्तकों की सीमा) | ||
(फ़िल्टर | (फ़िल्टर | ||
(लैम्ब्डा (पुस्तक) | |||
(>= (पुस्तक-बिक्री बही) सीमा)) | |||
पुस्तक सूची)) | |||
</वाक्यविन्यास हाइलाइट> | </वाक्यविन्यास हाइलाइट> | ||
इस उदाहरण में, [[लैम्ब्डा (प्रोग्रामिंग)]] <code>(lambda (book) (>= (book-sales book) threshold))</code> समारोह में प्रकट होता है <code>best-selling-books</code>. जब लैम्ब्डा अभिव्यक्ति का मूल्यांकन किया जाता है, तो योजना लैम्ब्डा अभिव्यक्ति के लिए कोड और संदर्भ के लिए | इस उदाहरण में, [[लैम्ब्डा (प्रोग्रामिंग)]] <code>(lambda (book) (>= (book-sales book) threshold))</code> समारोह में प्रकट होता है <code>best-selling-books</code>. जब लैम्ब्डा अभिव्यक्ति का मूल्यांकन किया जाता है, तो योजना लैम्ब्डा अभिव्यक्ति के लिए कोड और संदर्भ के लिए क्लोजर बनाती है <code>threshold</code> वेरिएबल, जो लैम्ब्डा एक्सप्रेशन के अंदर फ्री वेरिएबल है। | ||
इसके बाद क्लोजर को पास कर दिया जाता है <code>filter</code> फ़ंक्शन, जो यह निर्धारित करने के लिए बार-बार कॉल करता है कि परिणाम सूची में कौन सी पुस्तकें जोड़ी जानी हैं और कौन सी छोड़ी जानी हैं। क्योंकि बंद करने का ही | इसके बाद क्लोजर को पास कर दिया जाता है <code>filter</code> फ़ंक्शन, जो यह निर्धारित करने के लिए बार-बार कॉल करता है कि परिणाम सूची में कौन सी पुस्तकें जोड़ी जानी हैं और कौन सी छोड़ी जानी हैं। क्योंकि बंद करने का ही संदर्भ है <code>threshold</code>, यह हर बार उस चर का उपयोग कर सकता है <code>filter</code> इसे कहते हैं। कार्यक्रम <code>filter</code> स्वयं को पूरी तरह से अलग फ़ाइल में परिभाषित किया जा सकता है। | ||
यहाँ उसी उदाहरण को जावास्क्रिप्ट में फिर से लिखा गया है, क्लोजर के लिए समर्थन के साथ | यहाँ उसी उदाहरण को जावास्क्रिप्ट में फिर से लिखा गया है, क्लोजर के लिए समर्थन के साथ अन्य लोकप्रिय भाषा: | ||
<वाक्यविन्यास लैंग = जावास्क्रिप्ट> | <वाक्यविन्यास लैंग = जावास्क्रिप्ट> | ||
// बेची गई कम से कम 'दहलीज' प्रतियों वाली सभी पुस्तकों की सूची लौटाएं। | // बेची गई कम से कम 'दहलीज' प्रतियों वाली सभी पुस्तकों की सूची लौटाएं। | ||
सबसे अधिक बिकने वाली पुस्तकें (दहलीज) कार्य करें { | सबसे अधिक बिकने वाली पुस्तकें (दहलीज) कार्य करें { | ||
रिटर्न बुकलिस्ट.फ़िल्टर ( | रिटर्न बुकलिस्ट.फ़िल्टर ( | ||
समारोह (पुस्तक) {पुस्तक वापस करें। बिक्री> = सीमा; } | |||
); | |||
} | } | ||
</वाक्यविन्यास हाइलाइट> <code>function</code> की जगह यहाँ e> कीवर्ड का प्रयोग किया गया है <code>lambda</code>, और | </वाक्यविन्यास हाइलाइट> <code>function</code> की जगह यहाँ e> कीवर्ड का प्रयोग किया गया है <code>lambda</code>, और <code>Array.filter</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>filter</code> कार्य करता है, किन्तु अन्यथा संरचना और कोड का प्रभाव समान होता है। | ||
फ़ंक्शन क्लोजर बना सकता है और इसे वापस कर सकता है, जैसा कि निम्नलिखित उदाहरण में है: | |||
<वाक्यविन्यास लैंग = जावास्क्रिप्ट> | <वाक्यविन्यास लैंग = जावास्क्रिप्ट> | ||
// | // फ़ंक्शन लौटाएं जो f के व्युत्पन्न का अनुमान लगाता है | ||
// डीएक्स के अंतराल का उपयोग करना, जो उचित रूप से छोटा होना चाहिए। | // डीएक्स के अंतराल का उपयोग करना, जो उचित रूप से छोटा होना चाहिए। | ||
फ़ंक्शन डेरिवेटिव (एफ, डीएक्स) { | फ़ंक्शन डेरिवेटिव (एफ, डीएक्स) { | ||
वापसी समारोह (एक्स) { | वापसी समारोह (एक्स) { | ||
रिटर्न (एफ(एक्स + डीएक्स) - एफ(एक्स)) / डीएक्स; | |||
}; | }; | ||
} | } | ||
</वाक्यविन्यास हाइलाइट> | </वाक्यविन्यास हाइलाइट> | ||
क्योंकि इस | क्योंकि इस स्थितियों में क्लोजर फ़ंक्शन के निष्पादन को समाप्त कर देता है जो इसे बनाता है, चर <code>f</code> और <code>dx</code> समारोह के बाद लाइव <code>derivative</code> रिटर्न, यदि निष्पादन ने अपना दायरा छोड़ दिया हो और वे अब दिखाई नहीं दे रहे हैं। क्लोजर के बिना भाषाओं में, स्वचालित स्थानीय चर का जीवनकाल स्टैक फ्रेम के निष्पादन के साथ मेल खाता है जहां उस चर को घोषित किया जाता है। क्लोजर वाली भाषाओं में, चर तब तक उपस्तिथ रहना चाहिए जब तक कि किसी भी उपस्तिथा क्लोजर में उनके संदर्भ हों। यह सामान्यतः किसी प्रकार के [[कचरा संग्रह (कंप्यूटर विज्ञान)]] का उपयोग करके कार्यान्वित किया जाता है। | ||
=== राज्य प्रतिनिधित्व === | === राज्य प्रतिनिधित्व === | ||
किसी फ़ंक्शन को [[वर्ग (कंप्यूटर प्रोग्रामिंग)]] चर के | किसी फ़ंक्शन को [[वर्ग (कंप्यूटर प्रोग्रामिंग)]] चर के सेट के साथ जोड़ने के लिए क्लोजर का उपयोग किया जा सकता है, जो फ़ंक्शन के कई आमंत्रणों पर बना रहता है। चर का दायरा (प्रोग्रामिंग) केवल बंद-ओवर फ़ंक्शन को सम्मिलित करता है, इसलिए इसे अन्य प्रोग्राम कोड से एक्सेस नहीं किया जा सकता है। ये [[ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग]] में [[निजी चर]] के अनुरूप हैं, और वास्तव में क्लोजर प्रकार के ऑब्जेक्ट (कंप्यूटर विज्ञान) के अनुरूप हैं, विशेष रूप से [[समारोह वस्तु]], सार्वजनिक विधि (फ़ंक्शन कॉल) के साथ, और संभवतः कई निजी चर (बंद) -ओवर वेरिएबल्स)। | ||
स्टेटफुल लैंग्वेज में, क्लोजर का उपयोग राज्य के प्रतिनिधित्व और सूचनाओं को छिपाने के लिए प्रतिमानों को लागू करने के लिए किया जा सकता है, क्योंकि क्लोजर के अपवैल्यू (इसके क्लोज्ड-ओवर वेरिएबल्स) अनिश्चित चर (प्रोग्रामिंग) # स्कोप और हद के होते हैं, इसलिए | स्टेटफुल लैंग्वेज में, क्लोजर का उपयोग राज्य के प्रतिनिधित्व और सूचनाओं को छिपाने के लिए प्रतिमानों को लागू करने के लिए किया जा सकता है, क्योंकि क्लोजर के अपवैल्यू (इसके क्लोज्ड-ओवर वेरिएबल्स) अनिश्चित चर (प्रोग्रामिंग) # स्कोप और हद के होते हैं, इसलिए इनवोकेशन में स्थापित मूल्य बना रहता है अगले में उपलब्ध है। इस तरह से उपयोग किए जाने वाले क्लोजर में अब संदर्भित पारदर्शिता नहीं है, और इस प्रकार अब [[शुद्ध समारोह]] नहीं हैं; फिर भी, वे सामान्यतः अशुद्ध कार्यात्मक भाषाओं जैसे स्कीम (प्रोग्रामिंग भाषा) में उपयोग किए जाते हैं। | ||
=== अन्य उपयोग === | === अन्य उपयोग === | ||
क्लोजर के कई उपयोग हैं: | क्लोजर के कई उपयोग हैं: | ||
* क्योंकि बंद होने से मूल्यांकन में देरी होती है—अर्थात्, वे तब तक कुछ नहीं करते जब तक उन्हें बुलाया नहीं जाता—उनका उपयोग नियंत्रण संरचनाओं को परिभाषित करने के लिए किया जा सकता है। उदाहरण के लिए, स्मॉलटाक की सभी मानक नियंत्रण संरचनाएँ, जिनमें शाखाएँ (यदि/तब/अन्य) और लूप्स (जबकि और के लिए) | * क्योंकि बंद होने से मूल्यांकन में देरी होती है—अर्थात्, वे तब तक कुछ नहीं करते जब तक उन्हें बुलाया नहीं जाता—उनका उपयोग नियंत्रण संरचनाओं को परिभाषित करने के लिए किया जा सकता है। उदाहरण के लिए, स्मॉलटाक की सभी मानक नियंत्रण संरचनाएँ, जिनमें शाखाएँ (यदि/तब/अन्य) और लूप्स (जबकि और के लिए) सम्मिलित हैं, उन वस्तुओं का उपयोग करके परिभाषित की जाती हैं जिनके तरीके क्लोजर स्वीकार करते हैं। उपयोक्ता अपनी स्वयं की नियंत्रण संरचनाओं को भी आसानी से परिभाषित कर सकते हैं। | ||
* उन भाषाओं में जो असाइनमेंट को लागू करती हैं, | * उन भाषाओं में जो असाइनमेंट को लागू करती हैं, ही वातावरण के करीब कई फ़ंक्शन उत्पन्न किए जा सकते हैं, जिससे वे उस वातावरण को बदलकर निजी तौर पर संवाद करने में सक्षम हो जाते हैं। योजना में: | ||
<वाक्यविन्यास लैंग = योजना> | <वाक्यविन्यास लैंग = योजना> | ||
Line 147: | Line 147: | ||
* ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग सिस्टम को लागू करने के लिए क्लोजर का उपयोग किया जा सकता है।<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> | * ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग सिस्टम को लागू करने के लिए क्लोजर का उपयोग किया जा सकता है।<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> या GNU C में नेस्टेड फ़ंक्शंस।<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]] जैसी लेक्सिकल स्कोप सिस्टम है, में स्टैक प्रोग्रामिंग मॉडल का अभाव है और यह स्टैक-आधारित भाषाओं की सीमाओं से ग्रस्त नहीं है। योजना में क्लोजर स्वाभाविक रूप से व्यक्त किए जाते हैं। लैम्ब्डा फॉर्म कोड को संलग्न करता है, और इसके पर्यावरण के मुक्त चर कार्यक्रम के भीतर तब तक बने रहते हैं जब तक उन्हें संभवतः एक्सेस किया जा सकता है, और इसलिए उन्हें किसी अन्य योजना अभिव्यक्ति के रूप में स्वतंत्र रूप से उपयोग किया जा सकता है।{{citation needed|date=December 2014}} | स्कीम (प्रोग्रामिंग लैंग्वेज), जिसमें डायनेमिक वेरिएबल्स और कचरा संग्रह के साथ [[ALGOL]] जैसी लेक्सिकल स्कोप सिस्टम है, में स्टैक प्रोग्रामिंग मॉडल का अभाव है और यह स्टैक-आधारित भाषाओं की सीमाओं से ग्रस्त नहीं है। योजना में क्लोजर स्वाभाविक रूप से व्यक्त किए जाते हैं। लैम्ब्डा फॉर्म कोड को संलग्न करता है, और इसके पर्यावरण के मुक्त चर कार्यक्रम के भीतर तब तक बने रहते हैं जब तक उन्हें संभवतः एक्सेस किया जा सकता है, और इसलिए उन्हें किसी अन्य योजना अभिव्यक्ति के रूप में स्वतंत्र रूप से उपयोग किया जा सकता है।{{citation needed|date=December 2014}} | ||
क्लोजर समवर्ती संगणना के [[अभिनेता मॉडल]] में अभिनेताओं से निकटता से संबंधित हैं, जहां फ़ंक्शन के शाब्दिक वातावरण में मूल्यों को परिचित कहा जाता है। [[समवर्ती प्रोग्रामिंग]] भाषाओं में क्लोजर के लिए | क्लोजर समवर्ती संगणना के [[अभिनेता मॉडल]] में अभिनेताओं से निकटता से संबंधित हैं, जहां फ़ंक्शन के शाब्दिक वातावरण में मूल्यों को परिचित कहा जाता है। [[समवर्ती प्रोग्रामिंग]] भाषाओं में क्लोजर के लिए महत्वपूर्ण मुद्दा यह है कि क्या क्लोजर में वेरिएबल्स को अपडेट किया जा सकता है और यदि हां, तो इन अपडेट्स को कैसे सिंक्रोनाइज किया जा सकता है। अभिनेता समाधान प्रदान करते हैं।<ref>''[https://dspace.mit.edu/handle/1721.1/6935 Foundations of Actor Semantics]'' Will Clinger. MIT Mathematics Doctoral Dissertation. June 1981.</ref> | ||
क्लोजर फ़ंक्शन ऑब्जेक्ट्स से निकटता से संबंधित हैं; पूर्व से दूसरे में परिवर्तन को [[निष्क्रियता]] या [[लैम्ब्डा उठाना]] के रूप में जाना जाता है; क्लोजर रूपांतरण भी देखें।{{Citation needed|date=September 2011}} | क्लोजर फ़ंक्शन ऑब्जेक्ट्स से निकटता से संबंधित हैं; पूर्व से दूसरे में परिवर्तन को [[निष्क्रियता]] या [[लैम्ब्डा उठाना]] के रूप में जाना जाता है; क्लोजर रूपांतरण भी देखें।{{Citation needed|date=September 2011}} | ||
== शब्दार्थ में अंतर == | == शब्दार्थ में अंतर == | ||
=== शाब्दिक वातावरण === | === शाब्दिक वातावरण === | ||
जैसा कि अलग-अलग भाषाओं में हमेशा शाब्दिक वातावरण की | जैसा कि अलग-अलग भाषाओं में हमेशा शाब्दिक वातावरण की सामान्य परिभाषा नहीं होती है, उनके बंद होने की परिभाषा भी भिन्न हो सकती है। लेक्सिकल पर्यावरण की सामान्य रूप से आयोजित न्यूनतम परिभाषा इसे दायरे में बाध्यकारी सभी नामों के सेट के रूप में परिभाषित करती है, और यह भी कि किसी भी भाषा में बंद होने पर कब्जा करना पड़ता है। चूँकि [[चर (प्रोग्रामिंग)]] बाइंडिंग का अर्थ भी भिन्न होता है। अनिवार्य भाषाओं में, चर स्मृति में सापेक्ष स्थानों से जुड़ते हैं जो मूल्यों को संग्रहीत कर सकते हैं। चूँकि बाइंडिंग का सापेक्ष स्थान रनटाइम पर नहीं बदलता है, किन्तु बाउंड लोकेशन में मान बदल सकता है। ऐसी भाषाओं में, चूंकि क्लोजर बाइंडिंग को कैप्चर करता है, वेरिएबल पर कोई भी ऑपरेशन, चाहे क्लोजर से किया गया हो या नहीं, उसी रिलेटिव मेमोरी लोकेशन पर किया जाता है। इसे अधिकांशतः चर को संदर्भ द्वारा कैप्चर करना कहा जाता है। यहां ईसीएमएस्क्रिप्ट में अवधारणा को चित्रित करने वाला उदाहरण दिया गया है, जो ऐसी ही भाषा है: | ||
<वाक्यविन्यास लैंग = [[एकमा स्क्रिप्ट]]> | <वाक्यविन्यास लैंग = [[एकमा स्क्रिप्ट]]> | ||
Line 189: | Line 187: | ||
समारोह <code>foo</code> और वेरिएबल्स द्वारा संदर्भित क्लोजर <code>f</code> और <code>g</code> सभी स्थानीय चर द्वारा दर्शाए गए समान सापेक्ष स्मृति स्थान का उपयोग करते हैं <code>x</code>. | समारोह <code>foo</code> और वेरिएबल्स द्वारा संदर्भित क्लोजर <code>f</code> और <code>g</code> सभी स्थानीय चर द्वारा दर्शाए गए समान सापेक्ष स्मृति स्थान का उपयोग करते हैं <code>x</code>. | ||
कुछ उदाहरणों में उपरोक्त व्यवहार अवांछनीय हो सकता है, और | कुछ उदाहरणों में उपरोक्त व्यवहार अवांछनीय हो सकता है, और अलग शाब्दिक समापन को बांधना आवश्यक है। फिर से ईसीएमएस्क्रिप्ट में, इसका उपयोग करके किया जाएगा <code>Function.bind()</code>. | ||
=== उदाहरण 1: | === उदाहरण 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> | <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> | ||
<वाक्यविन्यास लैंग = एक्मास्क्रिप्ट> | <वाक्यविन्यास लैंग = एक्मास्क्रिप्ट> | ||
Line 206: | Line 204: | ||
</वाक्यविन्यास हाइलाइट> | </वाक्यविन्यास हाइलाइट> | ||
=== उदाहरण 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> | ||
<वाक्यविन्यास लैंग = एक्मास्क्रिप्ट> | <nowiki><वाक्यविन्यास लैंग = एक्मास्क्रिप्ट> | ||
var एलिमेंट्स = document.getElementsByTagName ('ए'); | var एलिमेंट्स = document.getElementsByTagName ('ए'); | ||
// गलत: ई 'फॉर' लूप वाले फ़ंक्शन के लिए बाध्य है, न कि हैंडल को बंद करने के लिए | // गलत: ई 'फॉर' लूप वाले फ़ंक्शन के लिए बाध्य है, न कि हैंडल को बंद करने के लिए | ||
के लिए (तत्वों का संस्करण) {e.onclick = फ़ंक्शन हैंडल () {अलर्ट (e.id);}} | के लिए (तत्वों का संस्करण) {e.onclick = फ़ंक्शन हैंडल () {अलर्ट (e.id);}} | ||
</वाक्यविन्यास हाइलाइट> | </वाक्यविन्यास हाइलाइट> | ||
यहाँ फिर से परिवर्तनशील <code>e</code> का उपयोग करके ब्लॉक के दायरे से बंधे होने की आवश्यकता होगी <code>handle.bind(this)</code> या <code>let</code> कीवर्ड। | यहाँ फिर से परिवर्तनशील </nowiki><code>e</code> का उपयोग करके ब्लॉक के दायरे से बंधे होने की आवश्यकता होगी <code>handle.bind(this)</code> या <code>let</code> कीवर्ड। | ||
दूसरी ओर, कई कार्यात्मक भाषाएं, जैसे एमएल (प्रोग्रामिंग भाषा), चर को सीधे मानों से बांधती हैं। इस | दूसरी ओर, कई कार्यात्मक भाषाएं, जैसे एमएल (प्रोग्रामिंग भाषा), चर को सीधे मानों से बांधती हैं। इस स्थितियों में, चूंकि बार बाध्य होने के बाद चर के मान को बदलने का कोई विधि नहीं है, राज्य को बंद करने के बीच साझा करने की कोई आवश्यकता नहीं है - वे केवल उसी मान का उपयोग करते हैं। इसे अधिकांशतः चर को मान द्वारा कैप्चर करना कहा जाता है। जावा के स्थानीय और अनाम वर्ग भी इस श्रेणी में आते हैं - उन्हें होने के लिए कैप्चर किए गए स्थानीय चर की आवश्यकता होती है <code>final</code>, जिसका अर्थ यह भी है कि राज्य को साझा करने की कोई आवश्यकता नहीं है। | ||
कुछ भाषाएँ आपको | कुछ भाषाएँ आपको चर या उसके स्थान के मान को कैप्चर करने के बीच चयन करने में सक्षम बनाती हैं। उदाहरण के लिए, सी ++ 11 में, कैप्चर किए गए चर या तो घोषित किए जाते हैं <code>[&]</code>, जिसका अर्थ है संदर्भ द्वारा या साथ में कब्जा कर लिया गया <code>[=]</code>, जिसका अर्थ है मूल्य द्वारा कब्जा कर लिया गया। | ||
फिर भी | फिर भी और सबसेट, [[आलसी मूल्यांकन]] कार्यात्मक भाषाएं जैसे [[हास्केल (प्रोग्रामिंग भाषा)]], मूल्यों के अतिरिक्त भविष्य की संगणनाओं के परिणामों के लिए चर को बांधती हैं। हास्केल में इस उदाहरण पर विचार करें: | ||
<वाक्यविन्यास लैंग = हैकेल> | <वाक्यविन्यास लैंग = हैकेल> | ||
Line 226: | Line 224: | ||
foo :: भिन्नात्मक a => a -> a -> (a -> a) | foo :: भिन्नात्मक a => a -> a -> (a -> a) | ||
फू x y = (\z -> z + r) | फू x y = (\z -> z + r) | ||
जहां आर = एक्स / वाई | |||
f :: भिन्नात्मक a => a -> a | f :: भिन्नात्मक a => a -> a | ||
Line 234: | Line 232: | ||
</वाक्यविन्यास हाइलाइट> | </वाक्यविन्यास हाइलाइट> | ||
का बंधन <code>r</code> फ़ंक्शन के भीतर परिभाषित क्लोजर द्वारा कैप्चर किया गया <code>foo</code> गणना के लिए है <code>(x / y)</code>—जो इस | का बंधन <code>r</code> फ़ंक्शन के भीतर परिभाषित क्लोजर द्वारा कैप्चर किया गया <code>foo</code> गणना के लिए है <code>(x / y)</code>—जो इस स्थितियों में शून्य से विभाजन में परिणत होता है। चूँकि, चूंकि यह अभिकलन है जो कैप्चर किया गया है, न कि मान, त्रुटि केवल तभी प्रकट होती है जब क्लोजर का आह्वान किया जाता है, और वास्तव में कैप्चर किए गए बाइंडिंग का उपयोग करने का प्रयास करता है। | ||
=== जा रहा बंद === | === जा रहा बंद === | ||
फिर भी अधिक अंतर स्वयं को अन्य व्याख्यात्मक रूप से निर्मित निर्माणों के व्यवहार में प्रकट करते हैं, जैसे कि <code>return</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 260: | Line 258: | ||
</वाक्यविन्यास हाइलाइट> | </वाक्यविन्यास हाइलाइट> | ||
उपरोक्त कोड स्निपेट्स अलग तरह से व्यवहार करेंगे क्योंकि स्मॉलटाक <code>^</code> ऑपरेटर और जावास्क्रिप्ट <code>return</code> ऑपरेटर अनुरूप नहीं हैं। ईसीएमएस्क्रिप्ट उदाहरण में, <code>return x</code> का | उपरोक्त कोड स्निपेट्स अलग तरह से व्यवहार करेंगे क्योंकि स्मॉलटाक <code>^</code> ऑपरेटर और जावास्क्रिप्ट <code>return</code> ऑपरेटर अनुरूप नहीं हैं। ईसीएमएस्क्रिप्ट उदाहरण में, <code>return x</code> का नया पुनरावृति प्रारंभ करने के लिए आंतरिक समापन को छोड़ देगा <code>forEach</code> पाश, जबकि स्मालटाक उदाहरण में, <code>^x</code> लूप को निरस्त कर देगा और विधि से वापस आ जाएगा <code>foo</code>. | ||
[[सामान्य लिस्प]] | [[सामान्य लिस्प]] निर्माण प्रदान करता है जो उपरोक्त कार्यों में से किसी को व्यक्त कर सकता है: लिस्प <code>(return-from foo x)</code> स्मॉलटाक के रूप में व्यवहार करता है <code>^x</code>, जबकि लिस्प <code>(return-from nil x)</code> जावास्क्रिप्ट के रूप में व्यवहार करता है <code>return x</code>. इसलिए, स्मॉलटॉक कैप्चर किए गए एस्केप निरंतरता को उस सीमा तक जीवित रहने के लिए संभव बनाता है जिसमें इसे सफलतापूर्वक लागू किया जा सकता है। विचार करना: | ||
<वाक्यविन्यास लैंग = स्मॉलटॉक> | <वाक्यविन्यास लैंग = स्मॉलटॉक> | ||
गपशप | गपशप | ||
फू | फू | ||
^[ :x | ^x] | |||
छड़ | छड़ | ||
| एफ | | |||
च�:= स्वयं फू. | |||
एफ मान: 123 त्रुटि! | |||
</वाक्यविन्यास हाइलाइट> | </वाक्यविन्यास हाइलाइट> | ||
जब बंद विधि द्वारा वापस आ गया <code>foo</code> आह्वान किया जाता है, यह के आह्वान से | जब बंद विधि द्वारा वापस आ गया <code>foo</code> आह्वान किया जाता है, यह के आह्वान से मान वापस करने का प्रयास करता है <code>foo</code> जिसने बंद बनाया। चूँकि वह कॉल पहले ही वापस आ चुकी है और स्मॉलटाक विधि मंगलाचरण मॉडल कई रिटर्न की सुविधा के लिए [[स्पेगेटी ढेर]] अनुशासन का पालन नहीं करता है, इस ऑपरेशन के परिणामस्वरूप त्रुटि होती है। | ||
कुछ भाषाएँ, जैसे [[रूबी (प्रोग्रामिंग भाषा)]], प्रोग्रामर को रास्ता चुनने में सक्षम बनाती हैं <code>return</code> कब्जा कर लिया है। रूबी में | कुछ भाषाएँ, जैसे [[रूबी (प्रोग्रामिंग भाषा)]], प्रोग्रामर को रास्ता चुनने में सक्षम बनाती हैं <code>return</code> कब्जा कर लिया है। रूबी में उदाहरण: | ||
<वाक्यविन्यास लैंग = रूबी> | <वाक्यविन्यास लैंग = रूबी> | ||
# माणिक | # माणिक | ||
# | # प्रोक का उपयोग कर बंद करें | ||
डेफ फू | डेफ फू | ||
f = Proc.new { foo से अंदर की खरीद से वापसी वापसी} | f = Proc.new { foo से अंदर की खरीद से वापसी वापसी} | ||
Line 299: | Line 297: | ||
</वाक्यविन्यास हाइलाइट> | </वाक्यविन्यास हाइलाइट> | ||
दोनों <code>Proc.new</code> और <code>lambda</code> इस उदाहरण में | दोनों <code>Proc.new</code> और <code>lambda</code> इस उदाहरण में क्लोजर बनाने के तरीके हैं, किन्तु इस तरह से बनाए गए क्लोजर के शब्दार्थ इसके संबंध में भिन्न हैं <code>return</code> कथन। | ||
स्कीम (प्रोग्रामिंग लैंग्वेज) में, की परिभाषा और कार्यक्षेत्र <code>return</code> नियंत्रण कथन स्पष्ट है (और उदाहरण के लिए केवल मनमाने ढंग से 'वापसी' नाम दिया गया है)। निम्नलिखित रूबी नमूने का सीधा अनुवाद है। | स्कीम (प्रोग्रामिंग लैंग्वेज) में, की परिभाषा और कार्यक्षेत्र <code>return</code> नियंत्रण कथन स्पष्ट है (और उदाहरण के लिए केवल मनमाने ढंग से 'वापसी' नाम दिया गया है)। निम्नलिखित रूबी नमूने का सीधा अनुवाद है। | ||
Line 309: | Line 307: | ||
(परिभाषित करें (फू) | (परिभाषित करें (फू) | ||
(कॉल/सीसी | (कॉल/सीसी | ||
(लैम्ब्डा (वापसी) | |||
(परिभाषित करें (एफ) (अंदर से फू से वापसी वापसी)) | |||
(एफ)�; नियंत्रण यहां फू छोड़ देता है | |||
(फू से वापसी वापसी)))) | |||
(परिभाषित करें (बार) | (परिभाषित करें (बार) | ||
(कॉल/सीसी | (कॉल/सीसी | ||
(लैम्ब्डा (वापसी) | |||
(परिभाषित करें (एफ) (कॉल/सीसी (लैम्ब्डा (वापसी) (लैम्ब्डा से वापसी)))) | |||
(एफ)�; नियंत्रण यहां बार नहीं छोड़ता | |||
(बार से वापसी वापसी)))) | |||
(प्रदर्शन (फू)); प्रिंट अंदर से फू से वापस आते हैं | (प्रदर्शन (फू)); प्रिंट अंदर से फू से वापस आते हैं | ||
Line 333: | Line 331: | ||
[[कॉलबैक (कंप्यूटर विज्ञान)]] एस। यह है | [[कॉलबैक (कंप्यूटर विज्ञान)]] एस। यह है | ||
कभी-कभी दो मान प्रदान करके कार्यान्वित किया जाता है जब | कभी-कभी दो मान प्रदान करके कार्यान्वित किया जाता है जब | ||
लाइब्रेरी के साथ कॉलबैक पंजीकृत करना: | लाइब्रेरी के साथ कॉलबैक पंजीकृत करना: फ़ंक्शन | ||
सूचक और | सूचक और अलग <code>void*</code> के लिए सूचक | ||
उपयोगकर्ता की पसंद का मनमाना डेटा। जब पुस्तकालय | उपयोगकर्ता की पसंद का मनमाना डेटा। जब पुस्तकालय | ||
कॉलबैक फ़ंक्शन निष्पादित करता है, यह डेटा के साथ गुजरता है | कॉलबैक फ़ंक्शन निष्पादित करता है, यह डेटा के साथ गुजरता है | ||
Line 340: | Line 338: | ||
उस समय कैप्चर की गई जानकारी को संदर्भित करने के लिए | उस समय कैप्चर की गई जानकारी को संदर्भित करने के लिए | ||
पुस्तकालय के साथ पंजीकृत। मुहावरा समान है | पुस्तकालय के साथ पंजीकृत। मुहावरा समान है | ||
कार्यक्षमता में बंद, | कार्यक्षमता में बंद, किन्तु सिंटैक्स में नहीं। | ||
<code>void*</code> de> पॉइंटर [[प्रकार की सुरक्षा]] नहीं है इसलिए यह C | <code>void*</code> de> पॉइंटर [[प्रकार की सुरक्षा]] नहीं है इसलिए यह C | ||
सी #, हास्केल या एमएल में टाइप-सेफ क्लोजर से मुहावरा अलग है। | सी #, हास्केल या एमएल में टाइप-सेफ क्लोजर से मुहावरा अलग है। | ||
Line 351: | Line 349: | ||
==== नेस्टेड फ़ंक्शन और फ़ंक्शन पॉइंटर (सी) ==== | ==== नेस्टेड फ़ंक्शन और फ़ंक्शन पॉइंटर (सी) ==== | ||
जीसीसी विस्तार के साथ, | जीसीसी विस्तार के साथ, [https://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html नेस्टेड फ़ंक्शन] का उपयोग किया जा सकता है और फ़ंक्शन पॉइंटर क्लोजर का अनुकरण कर सकता है, बशर्ते फ़ंक्शन युक्त दायरे से बाहर न हो। | ||
निम्न उदाहरण अमान्य है क्योंकि <code>adder</code> | निम्न उदाहरण अमान्य है क्योंकि <code>adder</code> शीर्ष-स्तरीय परिभाषा है (संकलक संस्करण के आधार पर, यह अनुकूलन के बिना संकलित होने पर सही परिणाम उत्पन्न कर सकता है, अर्थात <code>-O0</code>): | ||
<वाक्यविन्यास प्रकाश लैंग = सी> | <वाक्यविन्यास प्रकाश लैंग = सी> | ||
# | #सम्मिलित <stdio.h> | ||
टाइपपीफ इंट (*fn_int_to_int)(int); // फ़ंक्शन का प्रकार int->int | टाइपपीफ इंट (*fn_int_to_int)(int); // फ़ंक्शन का प्रकार int->int | ||
Line 361: | Line 359: | ||
fn_int_to_int योजक (पूर्णांक संख्या) { | fn_int_to_int योजक (पूर्णांक संख्या) { | ||
इंट ऐड (इंट वैल्यू) { रिटर्न वैल्यू + नंबर; } | इंट ऐड (इंट वैल्यू) { रिटर्न वैल्यू + नंबर; } | ||
वापसी और जोड़ें; // और ऑपरेटर यहाँ वैकल्पिक है क्योंकि C में | वापसी और जोड़ें; // और ऑपरेटर यहाँ वैकल्पिक है क्योंकि C में फ़ंक्शन का नाम पॉइंटर है जो स्वयं की ओर इशारा करता है | ||
} | } | ||
Line 371: | Line 369: | ||
</वाक्यविन्यास हाइलाइट> | </वाक्यविन्यास हाइलाइट> | ||
किन्तु चल रहा है <code>adder</code> (और, वैकल्पिक रूप से, <code>typedef</code>) में <code>main</code> इसे वैध बनाता है: | |||
<वाक्यविन्यास प्रकाश लैंग = सी> | <वाक्यविन्यास प्रकाश लैंग = सी> | ||
# | #सम्मिलित <stdio.h> | ||
पूर्णांक मुख्य (शून्य) { | पूर्णांक मुख्य (शून्य) { | ||
Line 380: | Line 378: | ||
fn_int_to_int योजक (पूर्णांक संख्या) { | fn_int_to_int योजक (पूर्णांक संख्या) { | ||
इंट ऐड (इंट वैल्यू) { रिटर्न वैल्यू + नंबर; } | |||
वापसी जोड़ें; | |||
} | } | ||
Line 393: | Line 391: | ||
=== स्थानीय वर्ग और लैम्ब्डा फ़ंक्शंस (जावा) === | === स्थानीय वर्ग और लैम्ब्डा फ़ंक्शंस (जावा) === | ||
[[जावा (प्रोग्रामिंग भाषा)]] [[क्लास (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग)]] को [[विधि (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग)]] के अंदर परिभाषित करने में सक्षम बनाता है। इन्हें स्थानीय वर्ग कहा जाता है। जब ऐसी कक्षाओं का नाम नहीं दिया जाता है, तो उन्हें [[अनाम वर्ग]] (या अनाम आंतरिक वर्ग) के रूप में जाना जाता है। | [[जावा (प्रोग्रामिंग भाषा)]] [[क्लास (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग)]] को [[विधि (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग)]] के अंदर परिभाषित करने में सक्षम बनाता है। इन्हें स्थानीय वर्ग कहा जाता है। जब ऐसी कक्षाओं का नाम नहीं दिया जाता है, तो उन्हें [[अनाम वर्ग]] (या अनाम आंतरिक वर्ग) के रूप में जाना जाता है। स्थानीय वर्ग (या तो नामित या अनाम) लेक्सिक रूप से संलग्न कक्षाओं में नामों का उल्लेख कर सकता है, या केवल-पढ़ने के लिए चर (के रूप में चिह्नित) <code>final</code>) शाब्दिक रूप से संलग्न विधि में। | ||
<वाक्यविन्यास प्रकाश लैंग = जावा> | <वाक्यविन्यास प्रकाश लैंग = जावा> | ||
वर्ग गणनाविंडो JFrame का विस्तार करता है { | वर्ग गणनाविंडो JFrame का विस्तार करता है { | ||
निजी अस्थिर इंट परिणाम; | |||
// ... | |||
सार्वजनिक शून्य गणना अलग-अलग थ्रेड (अंतिम यूआरआई यूरी) { | |||
// अभिव्यक्ति नया रननेबल () {...} 'रननेबल' इंटरफ़ेस को लागू करने वाला अनाम वर्ग है। | |||
नया सूत्र( | |||
नया रननेबल () { | |||
शून्य रन () { | |||
// यह अंतिम स्थानीय चर पढ़ सकता है: | |||
गणना (यूरी); | |||
// यह संलग्न वर्ग के निजी क्षेत्रों तक पहुँच सकता है: | |||
परिणाम = परिणाम + 10; | |||
} | |||
} | |||
)।प्रारंभ करना(); | |||
} | |||
} | } | ||
</वाक्यविन्यास हाइलाइट> | </वाक्यविन्यास हाइलाइट> | ||
का कब्जा <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 426: | Line 424: | ||
<वाक्यविन्यास प्रकाश लैंग = जावा> | <वाक्यविन्यास प्रकाश लैंग = जावा> | ||
वर्ग गणनाविंडो JFrame का विस्तार करता है { | वर्ग गणनाविंडो JFrame का विस्तार करता है { | ||
निजी अस्थिर इंट परिणाम; | |||
// ... | |||
सार्वजनिक शून्य गणना अलग-अलग थ्रेड (अंतिम यूआरआई यूरी) { | |||
// कोड () -> { /* कोड */} क्लोजर है। | |||
नया थ्रेड (() -> { | |||
गणना (यूरी); | |||
परिणाम = परिणाम + 10; | |||
})।प्रारंभ करना(); | |||
} | |||
} | } | ||
</वाक्यविन्यास हाइलाइट> | </वाक्यविन्यास हाइलाइट> | ||
स्थानीय वर्ग | स्थानीय वर्ग प्रकार के आंतरिक वर्ग हैं जो विधि के शरीर के भीतर घोषित किए जाते हैं। जावा आंतरिक कक्षाओं का भी समर्थन करता है जिन्हें संलग्न वर्ग के गैर-स्थैतिक सदस्यों के रूप में घोषित किया जाता है।<ref>{{cite web | ||
| url = https://blogs.oracle.com/darcy/entry/nested_inner_member_and_top | | url = https://blogs.oracle.com/darcy/entry/nested_inner_member_and_top | ||
| title = Nested, Inner, Member, and Top-Level Classes}}</ref> उन्हें | | title = Nested, Inner, Member, and Top-Level Classes}}</ref> उन्हें सामान्यतः आंतरिक कक्षाओं के रूप में संदर्भित किया जाता है।<ref>{{cite web | ||
| url = http://java.sun.com/docs/books/tutorial/java/javaOO/innerclasses.html | | url = http://java.sun.com/docs/books/tutorial/java/javaOO/innerclasses.html | ||
| title = Inner Class Example (The Java Tutorials > Learning the Java Language > Classes and Objects) | | title = Inner Class Example (The Java Tutorials > Learning the Java Language > Classes and Objects) | ||
}}</ref> इन्हें संलग्न वर्ग के शरीर में परिभाषित किया गया है और संलग्न वर्ग के आवृत्ति चरों तक पूर्ण पहुंच है। इन इंस्टेंस वेरिएबल्स के लिए उनके बंधन के कारण, | }}</ref> इन्हें संलग्न वर्ग के शरीर में परिभाषित किया गया है और संलग्न वर्ग के आवृत्ति चरों तक पूर्ण पहुंच है। इन इंस्टेंस वेरिएबल्स के लिए उनके बंधन के कारण, विशेष सिंटैक्स का उपयोग करके संलग्न वर्ग के उदाहरण के लिए स्पष्ट बंधन के साथ आंतरिक वर्ग को केवल तत्काल किया जा सकता है।<ref>{{cite web | ||
| url = http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html | | url = http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html | ||
| title = Nested Classes (The Java Tutorials > Learning the Java Language > Classes and Objects) | | title = Nested Classes (The Java Tutorials > Learning the Java Language > Classes and Objects) | ||
Line 449: | Line 447: | ||
<वाक्यविन्यास प्रकाश लैंग = जावा> | <वाक्यविन्यास प्रकाश लैंग = जावा> | ||
पब्लिक क्लास एनक्लोजिंग क्लास { | पब्लिक क्लास एनक्लोजिंग क्लास { | ||
/ * आंतरिक वर्ग को परिभाषित करें * / | |||
पब्लिक क्लास इनरक्लास { | |||
सार्वजनिक पूर्णांक वृद्धि और रिटर्न काउंटर () { | |||
वापसी काउंटर ++; | |||
} | |||
} | |||
निजी इंट काउंटर; | |||
{ | |||
काउंटर = 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 तक के पूर्णांकों को प्रिंट करेगा। इस प्रकार के वर्ग को नेस्टेड वर्ग के साथ भ्रमित न करने के लिए सावधान रहें, जो उसी तरह से घोषित किया जाता है जैसे स्थैतिक संशोधक के उपयोग के साथ; उनका वांछित प्रभाव नहीं है, बल्कि केवल वे वर्ग हैं जिनके पास | निष्पादन पर, यह 0 से 9 तक के पूर्णांकों को प्रिंट करेगा। इस प्रकार के वर्ग को नेस्टेड वर्ग के साथ भ्रमित न करने के लिए सावधान रहें, जो उसी तरह से घोषित किया जाता है जैसे स्थैतिक संशोधक के उपयोग के साथ; उनका वांछित प्रभाव नहीं है, बल्कि केवल वे वर्ग हैं जिनके पास संलग्न वर्ग में परिभाषित कोई विशेष बंधन नहीं है। | ||
जावा संस्करण इतिहास#Java_8 के रूप में, जावा प्रथम श्रेणी की वस्तुओं के रूप में कार्यों का समर्थन करता है। इस रूप के लैम्ब्डा भावों को प्रकार का माना जाता है <code>Function<T,U></code> जहां T डोमेन है और U छवि प्रकार है। इसके साथ व्यंजक कहा जा सकता है <code>.apply(T t)</code> विधि, | जावा संस्करण इतिहास#Java_8 के रूप में, जावा प्रथम श्रेणी की वस्तुओं के रूप में कार्यों का समर्थन करता है। इस रूप के लैम्ब्डा भावों को प्रकार का माना जाता है <code>Function<T,U></code> जहां T डोमेन है और U छवि प्रकार है। इसके साथ व्यंजक कहा जा सकता है <code>.apply(T t)</code> विधि, किन्तु मानक विधि कॉल के साथ नहीं। | ||
<वाक्यविन्यास प्रकाश लैंग = जावा> | <वाक्यविन्यास प्रकाश लैंग = जावा> | ||
सार्वजनिक स्थैतिक शून्य main (String [] args) { | सार्वजनिक स्थैतिक शून्य main (String [] args) { | ||
समारोह <स्ट्रिंग, पूर्णांक> लंबाई = s -> s.length (); | |||
System.out.println (लंबाई। लागू करें (हैलो, दुनिया!)); // 13 प्रिंट करेगा। | |||
} | } | ||
</वाक्यविन्यास हाइलाइट> | </वाक्यविन्यास हाइलाइट> | ||
=== ब्लॉक (सी, सी ++, ऑब्जेक्टिव-सी 2.0) === | === ब्लॉक (सी, सी ++, ऑब्जेक्टिव-सी 2.0) === | ||
{{Main| | {{Main|ब्लॉक (सी भाषा विस्तार)}} | ||
Apple Inc. ने C (प्रोग्रामिंग भाषा), [[C++]], ऑब्जेक्टिव-C 2.0 और Mac OS X स्नो लेपर्ड | Mac OS X 10.6 स्नो लेपर्ड और IOS ( सेब) | आईओएस 4.0। ऐप्पल ने जीसीसी और क्लैंग कंपाइलर्स के लिए अपना कार्यान्वयन उपलब्ध कराया। | Apple Inc. ने C (प्रोग्रामिंग भाषा), [[C++]], ऑब्जेक्टिव-C 2.0 और Mac OS X स्नो लेपर्ड | Mac OS X 10.6 स्नो लेपर्ड और IOS ( सेब) | आईओएस 4.0। ऐप्पल ने जीसीसी और क्लैंग कंपाइलर्स के लिए अपना कार्यान्वयन उपलब्ध कराया। | ||
Line 530: | Line 528: | ||
</वाक्यविन्यास हाइलाइट> | </वाक्यविन्यास हाइलाइट> | ||
डी (प्रोग्रामिंग लैंग्वेज) में, क्लोजर को डेलीगेट्स द्वारा लागू किया जाता है, | डी (प्रोग्रामिंग लैंग्वेज) में, क्लोजर को डेलीगेट्स द्वारा लागू किया जाता है, फंक्शन पॉइंटर को कॉन्टेक्स्ट पॉइंटर के साथ जोड़ा जाता है (उदाहरण के लिए क्लास इंस्टेंस, या क्लोजर के स्थितियों में हीप पर स्टैक फ्रेम)। | ||
<वाक्यविन्यास प्रकाश लैंग = डी> | <वाक्यविन्यास प्रकाश लैंग = डी> | ||
ऑटो टेस्ट 1 () { | ऑटो टेस्ट 1 () { | ||
इंट ए = 7; | |||
वापसी प्रतिनिधि () {वापसी + 3; }; // अनाम प्रतिनिधि निर्माण | |||
} | } | ||
ऑटो टेस्ट 2 () { | ऑटो टेस्ट 2 () { | ||
इंट ए = 20; | |||
इंट फू () {वापसी ए + 5; } // आंतरिक कार्य | |||
वापसी और फू; // प्रतिनिधि बनाने का दूसरा विधि | |||
} | } | ||
शून्य बार () { | शून्य बार () { | ||
ऑटो डीजी = test1 (); | |||
डीजी (); // = 10 // ठीक है, test1.a क्लोजर में है और अभी भी उपस्तिथ है | |||
डीजी = test2 (); | |||
डीजी (); // = 25 // ठीक है, test2.a बंद होने की स्थिति में है और अभी भी उपस्तिथ है | |||
} | } | ||
</वाक्यविन्यास हाइलाइट> | </वाक्यविन्यास हाइलाइट> | ||
D संस्करण 1 में सीमित क्लोजर समर्थन है। उदाहरण के लिए, उपरोक्त कोड सही ढंग से काम नहीं करेगा, क्योंकि चर a स्टैक पर है, और परीक्षण () से लौटने के बाद, यह अब इसका उपयोग करने के लिए मान्य नहीं है ( | D संस्करण 1 में सीमित क्लोजर समर्थन है। उदाहरण के लिए, उपरोक्त कोड सही ढंग से काम नहीं करेगा, क्योंकि चर a स्टैक पर है, और परीक्षण () से लौटने के बाद, यह अब इसका उपयोग करने के लिए मान्य नहीं है (संभवतः डीजी () के माध्यम से फू को कॉल करना, 'वापसी करेगा यादृच्छिक 'पूर्णांक)। इसे ढेर पर चर 'ए' को स्पष्ट रूप से आवंटित करके, या सभी आवश्यक बंद चरों को संग्रहीत करने के लिए स्ट्रक्चर्स या क्लास का उपयोग करके हल किया जा सकता है और उसी कोड को लागू करने वाली विधि से प्रतिनिधि का निर्माण किया जा सकता है। क्लोजर को अन्य कार्यों में पारित किया जा सकता है, जब तक कि वे केवल तब तक उपयोग किए जाते हैं जब संदर्भित मान अभी भी मान्य होते हैं (उदाहरण के लिए कॉलबैक पैरामीटर के रूप में क्लोजर के साथ किसी अन्य फ़ंक्शन को कॉल करना), और सामान्य डेटा प्रोसेसिंग कोड लिखने के लिए उपयोगी होते हैं, इसलिए यह सीमा , व्यवहार में, अधिकांशतः कोई समस्या नहीं होती है। | ||
यह सीमा डी संस्करण 2 में तय की गई थी - चर 'ए' स्वचालित रूप से हीप पर आवंटित किया जाएगा क्योंकि इसका उपयोग आंतरिक फ़ंक्शन में किया जाता है, और उस फ़ंक्शन का | यह सीमा डी संस्करण 2 में तय की गई थी - चर 'ए' स्वचालित रूप से हीप पर आवंटित किया जाएगा क्योंकि इसका उपयोग आंतरिक फ़ंक्शन में किया जाता है, और उस फ़ंक्शन का प्रतिनिधि वर्तमान दायरे से बच सकता है (डीजी या वापसी के लिए असाइनमेंट के माध्यम से)। कोई भी अन्य स्थानीय चर (या तर्क) जो प्रतिनिधियों द्वारा संदर्भित नहीं हैं या जो केवल प्रतिनिधियों द्वारा संदर्भित हैं जो वर्तमान दायरे से बाहर नहीं निकलते हैं, स्टैक पर बने रहते हैं, जो हीप आवंटन की तुलना में सरल और तेज़ है। आंतरिक वर्ग विधियों के लिए भी यही सच है जो किसी फ़ंक्शन के चर को संदर्भित करता है। | ||
=== फ़ंक्शन ऑब्जेक्ट्स (सी ++) === | === फ़ंक्शन ऑब्जेक्ट्स (सी ++) === | ||
Line 561: | Line 559: | ||
<वाक्यविन्यास लैंग = सीपीपी> | <वाक्यविन्यास लैंग = सीपीपी> | ||
शून्य फू (स्ट्रिंग मायनाम) { | शून्य फू (स्ट्रिंग मायनाम) { | ||
इंट वाई; | |||
वेक्टर <स्ट्रिंग> एन; | |||
// ... | |||
ऑटो मैं = एसटीडी::find_if(n.begin(), n.end(), | |||
// यह लैम्ब्डा अभिव्यक्ति है: | |||
[&] (स्थिरांक स्ट्रिंग और s) {वापसी s! = myname && s.size ()> y; } | |||
); | |||
// 'i' अब या तो 'n.end ()' है या 'n' में पहले स्ट्रिंग को इंगित करता है | |||
// जो 'myname' के बराबर नहीं है और जिसकी लंबाई 'y' से अधिक है | |||
} | } | ||
</वाक्यविन्यास हाइलाइट> | </वाक्यविन्यास हाइलाइट> | ||
=== इनलाइन एजेंट (एफिल) === | === इनलाइन एजेंट (एफिल) === | ||
एफिल (प्रोग्रामिंग लैंग्वेज) में क्लोजर को परिभाषित करने वाले इनलाइन एजेंट | एफिल (प्रोग्रामिंग लैंग्वेज) में क्लोजर को परिभाषित करने वाले इनलाइन एजेंट सम्मिलित हैं। इनलाइन एजेंट रूटीन का प्रतिनिधित्व करने वाली वस्तु है, जिसे रूटीन इन-लाइन का कोड देकर परिभाषित किया जाता है। उदाहरण के लिए, में | ||
<वाक्यविन्यास लैंग = एफिल> | <वाक्यविन्यास लैंग = एफिल> | ||
Line 584: | Line 582: | ||
</वाक्यविन्यास हाइलाइट> | </वाक्यविन्यास हाइलाइट> | ||
को तर्क <code>subscribe</code> | को तर्क <code>subscribe</code> एजेंट है, जो दो तर्कों के साथ प्रक्रिया का प्रतिनिधित्व करता है; प्रक्रिया देश को संबंधित निर्देशांक पर ढूंढती है और इसे प्रदर्शित करती है। पूरे एजेंट को ईवेंट प्रकार की सदस्यता दी गई है <code>click_event</code> के लिए | ||
निश्चित बटन, | निश्चित बटन, जिससे कि जब भी उस बटन पर घटना प्रकार का उदाहरण हो - क्योंकि उपयोगकर्ता ने बटन पर क्लिक किया है - प्रक्रिया को माउस निर्देशांक के साथ तर्क के रूप में पारित किया जाएगा <code>x</code> और <code>y</code>. | ||
एफिल एजेंटों की मुख्य सीमा, जो उन्हें अन्य भाषाओं में बंद होने से अलग करती है, यह है कि वे स्थानीय चर को संलग्न दायरे से संदर्भित नहीं कर सकते हैं। यह डिज़ाइन निर्णय अस्पष्टता से बचने में मदद करता है जब | एफिल एजेंटों की मुख्य सीमा, जो उन्हें अन्य भाषाओं में बंद होने से अलग करती है, यह है कि वे स्थानीय चर को संलग्न दायरे से संदर्भित नहीं कर सकते हैं। यह डिज़ाइन निर्णय अस्पष्टता से बचने में मदद करता है जब क्लोजर में स्थानीय चर मान के बारे में बात की जाती है - क्या यह चर का नवीनतम मान होना चाहिए या एजेंट के बनाए जाने पर कैप्चर किया गया मान होना चाहिए? केवल <code>Current</code> (वर्तमान वस्तु का संदर्भ, के अनुरूप <code>this</code> जावा में), इसकी विशेषताओं और एजेंट के तर्कों को एजेंट निकाय के भीतर से ही एक्सेस किया जा सकता है। एजेंट को अतिरिक्त बंद ऑपरेंड प्रदान करके बाहरी स्थानीय चर के मान पारित किए जा सकते हैं। | ||
=== सी ++ बिल्डर क्लोजर आरक्षित शब्द === | === सी ++ बिल्डर क्लोजर आरक्षित शब्द === | ||
Line 593: | Line 591: | ||
मानक C में आप a लिख सकते हैं {{mono|[[typedef]]}} निम्नलिखित सिंटैक्स का उपयोग करके फ़ंक्शन प्रकार के सूचक के लिए:<syntaxhighlight lang= c++ > | मानक C में आप a लिख सकते हैं {{mono|[[typedef]]}} निम्नलिखित सिंटैक्स का उपयोग करके फ़ंक्शन प्रकार के सूचक के लिए:<syntaxhighlight lang= c++ > | ||
टाइपपीफ शून्य (*TMyFunctionPointer) (शून्य); | टाइपपीफ शून्य (*TMyFunctionPointer) (शून्य); | ||
</syntaxhighlight>इसी प्रकार से आप घोषित कर सकते हैं a {{mono|typedef}} निम्नलिखित सिंटैक्स का उपयोग करने वाली विधि के लिए | </syntaxhighlight>इसी प्रकार से आप घोषित कर सकते हैं a {{mono|typedef}} निम्नलिखित सिंटैक्स का उपयोग करने वाली विधि के लिए सूचक के लिए:<nowiki><syntaxhighlight lang= c++ ></nowiki> | ||
टाइपपीफ शून्य (__closure *TMyMethodPointer) (); | टाइपपीफ शून्य (__closure *TMyMethodPointer) (); | ||
</वाक्यविन्यास हाइलाइट> | </वाक्यविन्यास हाइलाइट> |
Revision as of 11:17, 22 March 2023
प्रोग्रामिंग भाषाओं में, क्लोजर, लेक्सिकल क्लोजर या फंक्शन क्लोजर भी, प्रथम श्रेणी के कार्यों के साथ भाषा में लेक्सिकली स्कोप्ड नाम बंधन को लागू करने की तकनीक है। परिचालन शब्दार्थ, क्लोजर रिकॉर्ड (कंप्यूटर विज्ञान) है जो समारोह (कंप्यूटर विज्ञान) को स्टोर करता है[lower-alpha 1] साथ पर्यावरण के साथ।[1] पर्यावरण मानचित्रण है जो फ़ंक्शन के प्रत्येक मुक्त चर को जोड़ता है (वैरिएबल जो स्थानीय रूप से उपयोग किए जाते हैं, किन्तु संलग्न दायरे में परिभाषित होते हैं) मूल्य (कंप्यूटर विज्ञान) या संदर्भ (कंप्यूटर विज्ञान) के साथ जिसका नाम बंद होने पर नाम बाध्य था बनाया गया था .[lower-alpha 2] सादे फ़ंक्शन के विपरीत, क्लोजर फ़ंक्शन को उन कैप्चर किए गए चरों को उनके मूल्यों या संदर्भों की क्लोजर प्रतियों के माध्यम से एक्सेस करने की अनुमति देता है, तब भी जब फ़ंक्शन को उनके दायरे से बाहर बुलाया जाता है।
इतिहास और व्युत्पत्त
क्लोजर की अवधारणा को 1960 के दशक में λ-कैलकुलस में भावों के यांत्रिक मूल्यांकन के लिए विकसित किया गया था और पहली बार 1970 में पूरी तरह से आरपीएल प्रोग्रामिंग भाषा में भाषा सुविधा के रूप में लागू किया गया था जिससे कि लेक्सिक रूप से प्रथम श्रेणी के कार्यों का समर्थन किया जा सके।[2] पीटर जे. लैंडिन ने 1964 में टर्म क्लोजर को पर्यावरण भाग और नियंत्रण भाग के रूप में परिभाषित किया, जैसा कि अभिव्यक्ति के मूल्यांकन के लिए उनकी SECD मशीन द्वारा उपयोग किया जाता है।[3] जोएल मूसा लैंडिन को क्लोजर शब्द की शुरुआत करने का श्रेय देते हैं, जो बेनामी फ़ंक्शन को संदर्भित करता है, जिसके ओपन बाइंडिंग (फ्री वेरिएबल्स) को लेक्सिकल वातावरण द्वारा (या बाउंड इन) बंद कर दिया गया है, जिसके परिणामस्वरूप क्लोज्ड एक्सप्रेशन या क्लोजर होता है।[4][5] इस प्रयोग को बाद में गेराल्ड जे सुस्मान और गाइ एल. स्टील, जूनियर द्वारा अपनाया गया, जब उन्होंने 1975 में स्कीम (प्रोग्रामिंग भाषा) को परिभाषित किया,[6] लिस्प (प्रोग्रामिंग भाषा) का लेक्सिकली स्कोप्ड वेरिएंट, और व्यापक हो गया।
सुस्मान और हेरोल्ड एबेलसन भी 1980 के दशक में दूसरे, असंबंधित अर्थ के साथ क्लोजर शब्द का उपयोग करते हैं: ऑपरेटर की संपत्ति जो डेटा संरचना में डेटा जोड़ती है और नेस्टेड डेटा संरचनाओं को भी जोड़ने में सक्षम होती है। शब्द का यह उपयोग कंप्यूटर विज्ञान में पूर्व उपयोग के अतिरिक्त क्लोजर (गणित) से आता है। लेखक इस ओवरलैप को शब्दावली में दुर्भाग्यपूर्ण मानते हैं।[7]
अनाम कार्य
क्लोजर शब्द का प्रयोग अधिकांशतः अज्ञात फ़ंक्शन के पर्याय के रूप में किया जाता है, चूंकि सख्ती से, अनाम फ़ंक्शन फ़ंक्शन शाब्दिक (कंप्यूटर प्रोग्रामिंग) है, जिसका कोई नाम नहीं है, जबकि क्लोजर फ़ंक्शन का उदाहरण है, मान (कंप्यूटर विज्ञान), जिसका गैर -स्थानीय चर या तो मूल्यों या चर (कंप्यूटर विज्ञान) के लिए बाध्य हैं (भाषा के आधार पर; नीचे #Lexical पर्यावरण अनुभाग देखें)।
उदाहरण के लिए, निम्नलिखित पायथन (प्रोग्रामिंग भाषा) कोड में: <वाक्यविन्यास लैंग = अजगर> डेफ एफ (एक्स):
डेफ जी (वाई): रिटर्न एक्स + वाई रिटर्न जी # रिटर्न क्लोजर।
डीईएफ़ एच (एक्स):
रिटर्न लैम्ब्डा वाई: एक्स + वाई # क्लोजर लौटाएं।
- वेरिएबल्स को विशिष्ट क्लोजर असाइन करना।
ए = एफ (1) बी = एच (1)
- वेरिएबल्स में स्टोर किए गए क्लोजर का उपयोग करना।
ए (5) == 6 पर जोर दें जोर बी (5) == 6
- पहले वेरिएबल से बाइंड किए बिना क्लोजर का उपयोग करना।
जोर दें f(1)(5) == 6 # f(1) क्लोजर है।
जोर एच (1) (5) == 6 # एच (1) बंद है।
</वाक्यविन्यास हाइलाइट>
के मूल्य a
और b
क्लोजर हैं, दोनों स्थितियों में नेस्टेड फ़ंक्शन को एन्क्लोजिंग फ़ंक्शन से मुक्त चर के साथ लौटाकर उत्पादित किया जाता है, जिससे कि मुक्त चर पैरामीटर के मान से जुड़ा हो x
संलग्न समारोह का। में बंद हैं a
और b
कार्यात्मक रूप से समान हैं। कार्यान्वयन में एकमात्र अंतर यह है कि पहले स्थितियों में हमने नेस्टेड फ़ंक्शन का उपयोग नाम के साथ किया था, g
, जबकि दूसरे स्थितियों में हमने अनाम नेस्टेड फ़ंक्शन (Python कीवर्ड का उपयोग करके) का उपयोग किया lambda
अज्ञात फ़ंक्शन बनाने के लिए)। उन्हें परिभाषित करने में प्रयुक्त मूल नाम, यदि कोई हो, अप्रासंगिक है।
क्लोजर किसी भी अन्य वैल्यू की तरह वैल्यू है। इसे वेरिएबल को असाइन करने की आवश्यकता नहीं है और इसके अतिरिक्त इसे सीधे उपयोग किया जा सकता है, जैसा कि उदाहरण की अंतिम दो पंक्तियों में दिखाया गया है। इस उपयोग को अनाम क्लोजर माना जा सकता है।
नेस्टेड फ़ंक्शन परिभाषाएं स्वयं क्लोजर नहीं हैं: उनके पास फ्री वेरिएबल है जो अभी तक बाध्य नहीं है। केवल बार एनक्लोजिंग फ़ंक्शन का मूल्यांकन पैरामीटर के मान के साथ किया जाता है, नेस्टेड फ़ंक्शन बाउंड का फ्री वेरिएबल होता है, जो क्लोजर बनाता है, जिसे बाद में एनक्लोजिंग फ़ंक्शन से लौटाया जाता है।
अंत में, गैर-स्थानीय चर के दायरे से बाहर होने पर क्लोजर केवल मुक्त चर वाले फ़ंक्शन से अलग होता है, अन्यथा परिभाषित वातावरण और निष्पादन वातावरण मेल खाते हैं और इन्हें अलग करने के लिए कुछ भी नहीं है (स्थैतिक और गतिशील बाध्यकारी को अलग नहीं किया जा सकता है क्योंकि नाम समान मानों को हल करते हैं)। उदाहरण के लिए, नीचे दिए गए प्रोग्राम में, फ्री वेरिएबल के साथ कार्य करता है x
(गैर-स्थानीय चर के लिए बाध्य x
वैश्विक दायरे के साथ) उसी वातावरण में क्रियान्वित किए जाते हैं जहाँ x
परिभाषित किया गया है, इसलिए यह सारहीन है कि क्या ये वास्तव में बंद हैं:
<वाक्यविन्यास लैंग = अजगर>
एक्स = 1
अंक = [1, 2, 3]
डेफ एफ (वाई):
रिटर्न एक्स + वाई
नक्शा (एफ, अंक) नक्शा (लैम्ब्डा वाई: एक्स + वाई, अंक) </वाक्यविन्यास हाइलाइट> यह अधिकांशतः फ़ंक्शन रिटर्न द्वारा हासिल किया जाता है, क्योंकि फ़ंक्शन को गैर-स्थानीय चर के दायरे में परिभाषित किया जाना चाहिए, इस स्थितियों में सामान्यतः इसका दायरा छोटा होगा।
यह चर छायांकन (जो गैर-स्थानीय चर के दायरे को कम करता है) द्वारा भी प्राप्त किया जा सकता है, चूंकि व्यवहार में यह कम आम है, क्योंकि यह कम उपयोगी है और शैडोइंग को हतोत्साहित किया जाता है। इस उदाहरण में f
बंद होने के रूप में देखा जा सकता है क्योंकि x
के शरीर में f
के लिए बाध्य है x
वैश्विक नामस्थान में, नहीं x
स्थानीय के लिए g
:
<वाक्यविन्यास लैंग = अजगर>
एक्स = 0
डेफ एफ (वाई):
रिटर्न एक्स + वाई
डेफ जी (जेड):
x = 1 # स्थानीय x छाया वैश्विक x रिटर्न एफ (जेड)
g(1) # 1 का मूल्यांकन करता है, 2 का नहीं </वाक्यविन्यास हाइलाइट>
अनुप्रयोग
क्लोजर का उपयोग उन भाषाओं से जुड़ा हुआ है जहां कार्य प्रथम श्रेणी की वस्तुएं हैं, जिसमें उच्च-क्रम के कार्यों के परिणाम के रूप में कार्यों को वापस किया जा सकता है, या अन्य फ़ंक्शन कॉलों के लिए तर्क के रूप में पारित किया जा सकता है; यदि मुक्त चर वाले कार्य प्रथम श्रेणी के हैं, तो वापस लौटने से बंद हो जाता है। इसमें कार्यात्मक प्रोग्रामिंग भाषाएं जैसे लिस्प (प्रोग्रामिंग भाषा) और एमएल (प्रोग्रामिंग भाषा), साथ ही साथ कई आधुनिक, बहु-प्रतिमान भाषाएं सम्मिलित हैं, जैसे जूलिया (प्रोग्रामिंग भाषा), पायथन (प्रोग्रामिंग भाषा) और जंग (प्रोग्रामिंग भाषा)। कॉलबैक (कंप्यूटर प्रोग्रामिंग) के साथ क्लोजर का भी अधिकांशतः उपयोग किया जाता है, विशेष रूप से आयोजन प्रबंधकर्ता के लिए, जैसे कि जावास्क्रिप्ट में, जहां उनका उपयोग गतिशील वेब पेज के साथ बातचीत के लिए किया जाता है।
सूचनाओं को छिपाने के लिए क्लोजर का उपयोग निरंतरता-गुजरने वाली शैली में भी किया जा सकता है। वस्तु (कंप्यूटर विज्ञान) और नियंत्रण संरचनाओं जैसे निर्माण इस प्रकार बंद होने के साथ लागू किए जा सकते हैं। कुछ भाषाओं में, क्लोजर तब हो सकता है जब फ़ंक्शन को दूसरे फ़ंक्शन के भीतर परिभाषित किया जाता है, और आंतरिक फ़ंक्शन बाहरी फ़ंक्शन के स्थानीय चर को संदर्भित करता है। रन टाइम (प्रोग्राम जीवनचक्र चरण) | रन-टाइम पर, जब बाहरी फ़ंक्शन निष्पादित होता है, तो क्लोजर बनता है, जिसमें आंतरिक फ़ंक्शन का कोड होता है और क्लोजर के लिए आवश्यक बाहरी फ़ंक्शन के किसी भी चर के संदर्भ (अपवैल्यू) होते हैं।
प्रथम श्रेणी के कार्य
क्लोजर सामान्यतः प्रथम श्रेणी के ऑब्जेक्ट वाली भाषाओं में दिखाई देते हैं। प्रथम श्रेणी के कार्य-दूसरे शब्दों में, ऐसी भाषाएं फ़ंक्शन को तर्कों के रूप में पारित करने में सक्षम बनाती हैं, फ़ंक्शन कॉल से वापस आती हैं, चर नामों से बंधी होती हैं, आदि, सरल प्रकार जैसे स्ट्रिंग्स की तरह और पूर्णांक। उदाहरण के लिए, निम्नलिखित योजना (प्रोग्रामिंग भाषा) फ़ंक्शन पर विचार करें: <वाक्यविन्यास लैंग = योजना>
- बेची गई कम से कम थ्रेशोल्ड प्रतियों वाली सभी पुस्तकों की सूची लौटाएं।
(परिभाषित करें (सर्वाधिक बिकने वाली पुस्तकों की सीमा)
(फ़िल्टर (लैम्ब्डा (पुस्तक) (>= (पुस्तक-बिक्री बही) सीमा)) पुस्तक सूची))
</वाक्यविन्यास हाइलाइट>
इस उदाहरण में, लैम्ब्डा (प्रोग्रामिंग) (lambda (book) (>= (book-sales book) threshold))
समारोह में प्रकट होता है best-selling-books
. जब लैम्ब्डा अभिव्यक्ति का मूल्यांकन किया जाता है, तो योजना लैम्ब्डा अभिव्यक्ति के लिए कोड और संदर्भ के लिए क्लोजर बनाती है threshold
वेरिएबल, जो लैम्ब्डा एक्सप्रेशन के अंदर फ्री वेरिएबल है।
इसके बाद क्लोजर को पास कर दिया जाता है filter
फ़ंक्शन, जो यह निर्धारित करने के लिए बार-बार कॉल करता है कि परिणाम सूची में कौन सी पुस्तकें जोड़ी जानी हैं और कौन सी छोड़ी जानी हैं। क्योंकि बंद करने का ही संदर्भ है threshold
, यह हर बार उस चर का उपयोग कर सकता है filter
इसे कहते हैं। कार्यक्रम filter
स्वयं को पूरी तरह से अलग फ़ाइल में परिभाषित किया जा सकता है।
यहाँ उसी उदाहरण को जावास्क्रिप्ट में फिर से लिखा गया है, क्लोजर के लिए समर्थन के साथ अन्य लोकप्रिय भाषा: <वाक्यविन्यास लैंग = जावास्क्रिप्ट> // बेची गई कम से कम 'दहलीज' प्रतियों वाली सभी पुस्तकों की सूची लौटाएं। सबसे अधिक बिकने वाली पुस्तकें (दहलीज) कार्य करें {
रिटर्न बुकलिस्ट.फ़िल्टर ( समारोह (पुस्तक) {पुस्तक वापस करें। बिक्री> = सीमा; } );
}
</वाक्यविन्यास हाइलाइट> function
की जगह यहाँ e> कीवर्ड का प्रयोग किया गया है lambda
, और Array.filter
विधि[8] वैश्विक के अतिरिक्त filter
कार्य करता है, किन्तु अन्यथा संरचना और कोड का प्रभाव समान होता है।
फ़ंक्शन क्लोजर बना सकता है और इसे वापस कर सकता है, जैसा कि निम्नलिखित उदाहरण में है:
<वाक्यविन्यास लैंग = जावास्क्रिप्ट> // फ़ंक्शन लौटाएं जो f के व्युत्पन्न का अनुमान लगाता है // डीएक्स के अंतराल का उपयोग करना, जो उचित रूप से छोटा होना चाहिए। फ़ंक्शन डेरिवेटिव (एफ, डीएक्स) {
वापसी समारोह (एक्स) { रिटर्न (एफ(एक्स + डीएक्स) - एफ(एक्स)) / डीएक्स; };
} </वाक्यविन्यास हाइलाइट>
क्योंकि इस स्थितियों में क्लोजर फ़ंक्शन के निष्पादन को समाप्त कर देता है जो इसे बनाता है, चर f
और dx
समारोह के बाद लाइव derivative
रिटर्न, यदि निष्पादन ने अपना दायरा छोड़ दिया हो और वे अब दिखाई नहीं दे रहे हैं। क्लोजर के बिना भाषाओं में, स्वचालित स्थानीय चर का जीवनकाल स्टैक फ्रेम के निष्पादन के साथ मेल खाता है जहां उस चर को घोषित किया जाता है। क्लोजर वाली भाषाओं में, चर तब तक उपस्तिथ रहना चाहिए जब तक कि किसी भी उपस्तिथा क्लोजर में उनके संदर्भ हों। यह सामान्यतः किसी प्रकार के कचरा संग्रह (कंप्यूटर विज्ञान) का उपयोग करके कार्यान्वित किया जाता है।
राज्य प्रतिनिधित्व
किसी फ़ंक्शन को वर्ग (कंप्यूटर प्रोग्रामिंग) चर के सेट के साथ जोड़ने के लिए क्लोजर का उपयोग किया जा सकता है, जो फ़ंक्शन के कई आमंत्रणों पर बना रहता है। चर का दायरा (प्रोग्रामिंग) केवल बंद-ओवर फ़ंक्शन को सम्मिलित करता है, इसलिए इसे अन्य प्रोग्राम कोड से एक्सेस नहीं किया जा सकता है। ये ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग में निजी चर के अनुरूप हैं, और वास्तव में क्लोजर प्रकार के ऑब्जेक्ट (कंप्यूटर विज्ञान) के अनुरूप हैं, विशेष रूप से समारोह वस्तु, सार्वजनिक विधि (फ़ंक्शन कॉल) के साथ, और संभवतः कई निजी चर (बंद) -ओवर वेरिएबल्स)।
स्टेटफुल लैंग्वेज में, क्लोजर का उपयोग राज्य के प्रतिनिधित्व और सूचनाओं को छिपाने के लिए प्रतिमानों को लागू करने के लिए किया जा सकता है, क्योंकि क्लोजर के अपवैल्यू (इसके क्लोज्ड-ओवर वेरिएबल्स) अनिश्चित चर (प्रोग्रामिंग) # स्कोप और हद के होते हैं, इसलिए इनवोकेशन में स्थापित मूल्य बना रहता है अगले में उपलब्ध है। इस तरह से उपयोग किए जाने वाले क्लोजर में अब संदर्भित पारदर्शिता नहीं है, और इस प्रकार अब शुद्ध समारोह नहीं हैं; फिर भी, वे सामान्यतः अशुद्ध कार्यात्मक भाषाओं जैसे स्कीम (प्रोग्रामिंग भाषा) में उपयोग किए जाते हैं।
अन्य उपयोग
क्लोजर के कई उपयोग हैं:
- क्योंकि बंद होने से मूल्यांकन में देरी होती है—अर्थात्, वे तब तक कुछ नहीं करते जब तक उन्हें बुलाया नहीं जाता—उनका उपयोग नियंत्रण संरचनाओं को परिभाषित करने के लिए किया जा सकता है। उदाहरण के लिए, स्मॉलटाक की सभी मानक नियंत्रण संरचनाएँ, जिनमें शाखाएँ (यदि/तब/अन्य) और लूप्स (जबकि और के लिए) सम्मिलित हैं, उन वस्तुओं का उपयोग करके परिभाषित की जाती हैं जिनके तरीके क्लोजर स्वीकार करते हैं। उपयोक्ता अपनी स्वयं की नियंत्रण संरचनाओं को भी आसानी से परिभाषित कर सकते हैं।
- उन भाषाओं में जो असाइनमेंट को लागू करती हैं, ही वातावरण के करीब कई फ़ंक्शन उत्पन्न किए जा सकते हैं, जिससे वे उस वातावरण को बदलकर निजी तौर पर संवाद करने में सक्षम हो जाते हैं। योजना में:
<वाक्यविन्यास लैंग = योजना> (फू #f परिभाषित करें) (बार #f परिभाषित करें)
(चलो ((गुप्त-संदेश कोई नहीं))
(सेट! फू (लैम्ब्डा (संदेश) (सेट! गुप्त-संदेश संदेश))) (सेट! बार (लैम्ब्डा () गुप्त-संदेश)))
(प्रदर्शन (बार)); प्रिंट कोई नहीं (नई पंक्ति) (आधी रात को मुझे गोदी से मिलो) (प्रदर्शन (बार)); प्रिंट मुझसे आधी रात को डॉक पर मिलते हैं </वाक्यविन्यास हाइलाइट>
- ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग सिस्टम को लागू करने के लिए क्लोजर का उपयोग किया जा सकता है।[9]
नोट: कुछ समया किसी भी डेटा संरचना को कॉल करते हैं जो स्कोप (प्रोग्रामिंग) # लेक्सिकल स्कोपिंग वातावरण को क्लोजर से बांधता है, किन्तु यह शब्द सामान्यतः विशेष रूप से फ़ंक्शंस को संदर्भित करता है।
कार्यान्वयन और सिद्धांत
क्लोजर सामान्यतः विशेष डेटा संरचना के साथ कार्यान्वित किया जाता है जिसमें समारोह सूचक होता है, साथ ही फ़ंक्शन के लेक्सिकल पर्यावरण (अर्थात, उपलब्ध चर का सेट) का प्रतिनिधित्व उस समय होता है जब क्लोजर बनाया गया था। सन्दर्भ देने वाला पर्यावरण नाम गैर-स्थानीय नामों को लेक्सिकल वातावरण में संगत चरों के साथ बांधता है, जब क्लोजर बनाया जाता है, इसके अतिरिक्त उनके जीवनकाल को कम से कम क्लोजर के जीवनकाल तक विस्तारित करता है। जब क्लोजर को बाद के समय में अंकित किया जाता है, संभवतः अलग लेक्सिकल वातावरण के साथ, फ़ंक्शन को इसके गैर-स्थानीय चर के साथ निष्पादित किया जाता है, जो कि क्लोजर द्वारा कब्जा कर लिया गया है, न कि वर्तमान वातावरण।
भाषा कार्यान्वयन आसानी से पूर्ण क्लोजर का समर्थन नहीं कर सकता है यदि इसका रन-टाइम मेमोरी मॉडल रैखिक स्टैक-आधारित मेमोरी आवंटन पर सभी स्वचालित चर आवंटित करता है। ऐसी भाषाओं में, फ़ंक्शन के वापस आने पर किसी फ़ंक्शन के स्वचालित स्थानीय चरों को हटा दिया जाता है। चूँकि, क्लोजर के लिए यह आवश्यक है कि इसके द्वारा संदर्भित फ्री वेरिएबल्स एनक्लोजिंग फंक्शन के निष्पादन से बचे रहें। इसलिए, उन चरों को आवंटित किया जाना चाहिए जिससे कि वे तब तक बने रहें जब तक कि उनकी आवश्यकता न हो, सामान्यतः स्टैक के अतिरिक्त हीप आवंटन के माध्यम से, और उनके जीवनकाल को प्रबंधित किया जाना चाहिए जिससे कि वे तब तक जीवित रहें जब तक कि उन्हें संदर्भित करने वाले सभी क्लोजर अब उपयोग में न हों।
यह बताता है कि क्यों, सामान्यतः, मूल रूप से क्लोजर का समर्थन करने वाली भाषाएं कचरा संग्रह (कंप्यूटर विज्ञान) का उपयोग करती हैं। विकल्प गैर-स्थानीय चर के मैनुअल मेमोरी प्रबंधन हैं (स्पष्ट रूप से हीप पर आवंटन और किए जाने पर मुक्त), या, यदि स्टैक आवंटन का उपयोग करते हैं, तो भाषा के लिए यह स्वीकार करने के लिए कि कुछ उपयोग के स्थितियों अपरिभाषित व्यवहार की ओर ले जाएंगे, लटकने वाले पॉइंटर्स के कारण सी ++ 11 में लैम्ब्डा एक्सप्रेशन के रूप में मुक्त स्वचालित चर[10] या GNU C में नेस्टेड फ़ंक्शंस।[11] funarg समस्या (या कार्यात्मक तर्क समस्या) सी या सी ++ जैसी स्टैक-आधारित प्रोग्रामिंग भाषा में प्रथम श्रेणी की वस्तुओं के रूप में कार्यों को लागू करने में कठिनाई का वर्णन करती है। इसी तरह डी (प्रोग्रामिंग भाषा) वर्जन 1 में, यह माना जाता है कि प्रोग्रामर जानता है कि प्रतिनिधिमंडल (प्रोग्रामिंग) और स्वचालित स्थानीय चर के साथ क्या करना है, क्योंकि इसकी परिभाषा के दायरे से लौटने के बाद उनके संदर्भ अमान्य हो जाएंगे (स्वचालित स्थानीय चर ढेर पर हैं) ) - यह अभी भी कई उपयोगी कार्यात्मक पैटर्न की अनुमति देता है, किन्तु जटिल स्थितियों के लिए चर के लिए स्पष्ट हीप आवंटन की आवश्यकता होती है। डी संस्करण 2 ने यह पता लगाने के द्वारा हल किया कि कौन से चर को ढेर पर संग्रहीत किया जाना चाहिए, और स्वचालित आवंटन करता है। क्योंकि डी कचरा संग्रह का उपयोग करता है, दोनों संस्करणों में, चर के उपयोग को ट्रैक करने की कोई आवश्यकता नहीं है क्योंकि वे पास हो गए हैं।
अपरिवर्तनीय डेटा (जैसे एरलांग (प्रोग्रामिंग भाषा)) के साथ सख्त कार्यात्मक भाषाओं में, स्वचालित मेमोरी प्रबंधन (कचरा संग्रह) को लागू करना बहुत आसान है, क्योंकि चर के संदर्भों में कोई संभावित चक्र नहीं हैं। उदाहरण के लिए, एरलांग में, सभी तर्क और चर ढेर पर आवंटित किए जाते हैं, किन्तु उनके संदर्भ अतिरिक्त रूप से ढेर पर संग्रहीत होते हैं। फ़ंक्शन के वापस आने के बाद, संदर्भ अभी भी मान्य हैं। वृद्धिशील कचरा संग्राहक द्वारा हीप की सफाई की जाती है।
एमएल में, स्थानीय चर लेक्सिक रूप से स्कॉप्ड होते हैं, और इसलिए स्टैक-जैसे मॉडल को परिभाषित करते हैं, किन्तु चूंकि वे मूल्यों के लिए बाध्य हैं और वस्तुओं के लिए नहीं, कार्यान्वयन इन मानों को क्लोजर की डेटा संरचना में कॉपी करने के लिए स्वतंत्र है जो कि अदृश्य है प्रोग्रामर।
स्कीम (प्रोग्रामिंग लैंग्वेज), जिसमें डायनेमिक वेरिएबल्स और कचरा संग्रह के साथ ALGOL जैसी लेक्सिकल स्कोप सिस्टम है, में स्टैक प्रोग्रामिंग मॉडल का अभाव है और यह स्टैक-आधारित भाषाओं की सीमाओं से ग्रस्त नहीं है। योजना में क्लोजर स्वाभाविक रूप से व्यक्त किए जाते हैं। लैम्ब्डा फॉर्म कोड को संलग्न करता है, और इसके पर्यावरण के मुक्त चर कार्यक्रम के भीतर तब तक बने रहते हैं जब तक उन्हें संभवतः एक्सेस किया जा सकता है, और इसलिए उन्हें किसी अन्य योजना अभिव्यक्ति के रूप में स्वतंत्र रूप से उपयोग किया जा सकता है।[citation needed] क्लोजर समवर्ती संगणना के अभिनेता मॉडल में अभिनेताओं से निकटता से संबंधित हैं, जहां फ़ंक्शन के शाब्दिक वातावरण में मूल्यों को परिचित कहा जाता है। समवर्ती प्रोग्रामिंग भाषाओं में क्लोजर के लिए महत्वपूर्ण मुद्दा यह है कि क्या क्लोजर में वेरिएबल्स को अपडेट किया जा सकता है और यदि हां, तो इन अपडेट्स को कैसे सिंक्रोनाइज किया जा सकता है। अभिनेता समाधान प्रदान करते हैं।[12] क्लोजर फ़ंक्शन ऑब्जेक्ट्स से निकटता से संबंधित हैं; पूर्व से दूसरे में परिवर्तन को निष्क्रियता या लैम्ब्डा उठाना के रूप में जाना जाता है; क्लोजर रूपांतरण भी देखें।[citation needed]
शब्दार्थ में अंतर
शाब्दिक वातावरण
जैसा कि अलग-अलग भाषाओं में हमेशा शाब्दिक वातावरण की सामान्य परिभाषा नहीं होती है, उनके बंद होने की परिभाषा भी भिन्न हो सकती है। लेक्सिकल पर्यावरण की सामान्य रूप से आयोजित न्यूनतम परिभाषा इसे दायरे में बाध्यकारी सभी नामों के सेट के रूप में परिभाषित करती है, और यह भी कि किसी भी भाषा में बंद होने पर कब्जा करना पड़ता है। चूँकि चर (प्रोग्रामिंग) बाइंडिंग का अर्थ भी भिन्न होता है। अनिवार्य भाषाओं में, चर स्मृति में सापेक्ष स्थानों से जुड़ते हैं जो मूल्यों को संग्रहीत कर सकते हैं। चूँकि बाइंडिंग का सापेक्ष स्थान रनटाइम पर नहीं बदलता है, किन्तु बाउंड लोकेशन में मान बदल सकता है। ऐसी भाषाओं में, चूंकि क्लोजर बाइंडिंग को कैप्चर करता है, वेरिएबल पर कोई भी ऑपरेशन, चाहे क्लोजर से किया गया हो या नहीं, उसी रिलेटिव मेमोरी लोकेशन पर किया जाता है। इसे अधिकांशतः चर को संदर्भ द्वारा कैप्चर करना कहा जाता है। यहां ईसीएमएस्क्रिप्ट में अवधारणा को चित्रित करने वाला उदाहरण दिया गया है, जो ऐसी ही भाषा है:
<वाक्यविन्यास लैंग = एकमा स्क्रिप्ट> // जावास्क्रिप्ट वार एफ, जी; समारोह फू () {
वार एक्स; च = समारोह () {वापसी ++x; }; जी = समारोह () {वापसी --x; }; एक्स = 1; चेतावनी ('फू के अंदर, एफ को कॉल करें):' + एफ ());
} फू (); // 2 चेतावनी ('जी को कॉल करें):' + जी ()); // 1 (--x) चेतावनी ('जी को कॉल करें):' + जी ()); // 0 (--x) चेतावनी ('कॉल टू एफ ():' + एफ ()); // 1 (++x) चेतावनी ('कॉल टू एफ ():' + एफ ()); // 2 (++x) </वाक्यविन्यास हाइलाइट>
समारोह foo
और वेरिएबल्स द्वारा संदर्भित क्लोजर f
और g
सभी स्थानीय चर द्वारा दर्शाए गए समान सापेक्ष स्मृति स्थान का उपयोग करते हैं x
.
कुछ उदाहरणों में उपरोक्त व्यवहार अवांछनीय हो सकता है, और अलग शाब्दिक समापन को बांधना आवश्यक है। फिर से ईसीएमएस्क्रिप्ट में, इसका उपयोग करके किया जाएगा Function.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 में, कैप्चर किए गए चर या तो घोषित किए जाते हैं [&]
, जिसका अर्थ है संदर्भ द्वारा या साथ में कब्जा कर लिया गया [=]
, जिसका अर्थ है मूल्य द्वारा कब्जा कर लिया गया।
फिर भी और सबसेट, आलसी मूल्यांकन कार्यात्मक भाषाएं जैसे हास्केल (प्रोग्रामिंग भाषा), मूल्यों के अतिरिक्त भविष्य की संगणनाओं के परिणामों के लिए चर को बांधती हैं। हास्केल में इस उदाहरण पर विचार करें:
<वाक्यविन्यास लैंग = हैकेल> -- हास्केल foo :: भिन्नात्मक a => a -> a -> (a -> a) फू x y = (\z -> z + r)
जहां आर = एक्स / वाई
f :: भिन्नात्मक a => a -> a एफ = फू 1 0
मुख्य = प्रिंट (एफ 123) </वाक्यविन्यास हाइलाइट>
का बंधन r
फ़ंक्शन के भीतर परिभाषित क्लोजर द्वारा कैप्चर किया गया foo
गणना के लिए है (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
लूप को निरस्त कर देगा और विधि से वापस आ जाएगा foo
.
सामान्य लिस्प निर्माण प्रदान करता है जो उपरोक्त कार्यों में से किसी को व्यक्त कर सकता है: लिस्प (return-from foo x)
स्मॉलटाक के रूप में व्यवहार करता है ^x
, जबकि लिस्प (return-from nil x)
जावास्क्रिप्ट के रूप में व्यवहार करता है return x
. इसलिए, स्मॉलटॉक कैप्चर किए गए एस्केप निरंतरता को उस सीमा तक जीवित रहने के लिए संभव बनाता है जिसमें इसे सफलतापूर्वक लागू किया जा सकता है। विचार करना:
<वाक्यविन्यास लैंग = स्मॉलटॉक>
गपशप
फू
^[ :x | ^x]
छड़
| एफ | च�:= स्वयं फू. एफ मान: 123 त्रुटि!
</वाक्यविन्यास हाइलाइट>
जब बंद विधि द्वारा वापस आ गया foo
आह्वान किया जाता है, यह के आह्वान से मान वापस करने का प्रयास करता है foo
जिसने बंद बनाया। चूँकि वह कॉल पहले ही वापस आ चुकी है और स्मॉलटाक विधि मंगलाचरण मॉडल कई रिटर्न की सुविधा के लिए स्पेगेटी ढेर अनुशासन का पालन नहीं करता है, इस ऑपरेशन के परिणामस्वरूप त्रुटि होती है।
कुछ भाषाएँ, जैसे रूबी (प्रोग्रामिंग भाषा), प्रोग्रामर को रास्ता चुनने में सक्षम बनाती हैं return
कब्जा कर लिया है। रूबी में उदाहरण:
<वाक्यविन्यास लैंग = रूबी>
- माणिक
- प्रोक का उपयोग कर बंद करें
डेफ फू
f = Proc.new { foo से अंदर की खरीद से वापसी वापसी} f.call # control फू को यहां छोड़ देता है फू से वापसी
अंत
- लैम्ब्डा का उपयोग करके बंद करें
डेफ बार
f = लैम्ब्डा {लैम्ब्डा से रिटर्न रिटर्न} f.call # नियंत्रण यहां बार नहीं छोड़ता है बार से वापसी वापसी
अंत
पुट फू # प्रिंट फू फ्रॉम इनसाइड प्रो बार डालता है # बार से रिटर्न प्रिंट करता है </वाक्यविन्यास हाइलाइट>
दोनों Proc.new
और lambda
इस उदाहरण में क्लोजर बनाने के तरीके हैं, किन्तु इस तरह से बनाए गए क्लोजर के शब्दार्थ इसके संबंध में भिन्न हैं 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 के रूप में, जावा प्रथम श्रेणी की वस्तुओं के रूप में कार्यों का समर्थन करता है। इस रूप के लैम्ब्डा भावों को प्रकार का माना जाता है Function<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) (); </वाक्यविन्यास हाइलाइट>
यह भी देखें
- बेनामी समारोह
- ब्लॉक (सी भाषा विस्तार)
- कमांड पैटर्न
- जारी
- करी
- फंगस की समस्या
- लैम्ब्डा कैलकुलस
- आलसी मूल्यांकन
- आंशिक आवेदन
- स्पेगेटी स्टैक
- सिंटैक्टिक क्लोजर
- मूल्य-स्तरीय प्रोग्रामिंग
टिप्पणियाँ
- ↑ The function may be stored as a reference to a function, such as a function pointer.
- ↑ 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 "Lambda 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 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.