स्कोप (कंप्यूटर साइंस): Difference between revisions
m (49 revisions imported from alpha:स्कोप_(कंप्यूटर_साइंस)) |
No edit summary |
||
Line 707: | Line 707: | ||
{{refend}} | {{refend}} | ||
{{DEFAULTSORT:Scope (Programming)}} | {{DEFAULTSORT:Scope (Programming)}} | ||
[[de:Variable (Programmierung)#Sichtbarkeitsbereich von Variablen (Scope)]] | [[de:Variable (Programmierung)#Sichtbarkeitsbereich von Variablen (Scope)]] | ||
[[Category:All articles needing additional references|Scope (Programming)]] | |||
[[Category:All articles to be expanded|Scope (Programming)]] | |||
[[Category: | [[Category:All articles with unsourced statements|Scope (Programming)]] | ||
[[Category:Created On 17/02/2023]] | [[Category:Articles needing additional references from December 2008|Scope (Programming)]] | ||
[[Category:Vigyan Ready]] | [[Category:Articles to be expanded from अप्रैल 2013|Scope (Programming)]] | ||
[[Category:Articles using small message boxes|Scope (Programming)]] | |||
[[Category:Articles with hatnote templates targeting a nonexistent page|Scope (Programming)]] | |||
[[Category:Articles with invalid date parameter in template|Scope (Programming)]] | |||
[[Category:Articles with unsourced statements from June 2012|Scope (Programming)]] | |||
[[Category:Articles with unsourced statements from March 2022|Scope (Programming)]] | |||
[[Category:CS1 errors]] | |||
[[Category:Created On 17/02/2023|Scope (Programming)]] | |||
[[Category:Lua-based templates|Scope (Programming)]] | |||
[[Category:Machine Translated Page|Scope (Programming)]] | |||
[[Category:Pages with script errors|Scope (Programming)]] | |||
[[Category:Short description with empty Wikidata description|Scope (Programming)]] | |||
[[Category:Templates Vigyan Ready|Scope (Programming)]] | |||
[[Category:Templates that add a tracking category|Scope (Programming)]] | |||
[[Category:Templates that generate short descriptions|Scope (Programming)]] | |||
[[Category:Templates using TemplateData|Scope (Programming)]] | |||
[[Category:उदाहरण आर कोड वाले लेख|Scope (Programming)]] | |||
[[Category:प्रोग्रामिंग भाषा अवधारणाओं|Scope (Programming)]] |
Latest revision as of 10:55, 20 March 2023
कंप्यूटर प्रोग्रामिंग में, एक नेम बाइंडिंग का स्कोप(किसी इकाई के लिए एक नाम का जुड़ाव, जैसे कि एक वेरिएबल) एक कंप्यूटर प्रोग्राम का भाग है जहां बाइंडिंग बाध्यकारी मान्य है; यानी, जहां इकाई को संदर्भित करने के लिए नाम का उपयोग किया जा सकता है। प्रोग्राम के अन्य भागों में, नाम एक अलग इकाई (इसकी एक अलग बाइंडिंग हो सकती है), या कुछ भी नहीं (यह असीमित हो सकता है) को संदर्भित कर सकता है। स्कोप एक ही नाम को अलग-अलग ऑब्जेक्ट्स को संदर्भित करने की अनुमति देकर नाम टकराव को रोकने में मदद करता है - जब तक कि नामों के अलग-अलग स्कोप हों। एक नेम बाइंडिंग के स्कोप को एक इकाई की दृश्यता के रूप में भी जाना जाता है, विशेष रूप से पुराने या अधिक तकनीकी साहित्य में - यह संदर्भित इकाई के नाम से नहीं परिप्रेक्ष्य से है।
स्कोप शब्द का उपयोग 'सभी' नेम बाइंडिंग के समूह को संदर्भित करने के लिए भी किया जाता है जो किसी प्रोग्राम के एक भाग के भीतर या किसी प्रोग्राम में दिए गए बिंदु पर मान्य होते हैं, जिसे अधिक सही ढंग से 'संदर्भ' या पर्यावरण के रूप में संदर्भित किया जाता है।[lower-alpha 1]
सच पूछिये तो[lower-alpha 2] अधिकांश प्रोग्रामिंग भाषाओं के लिए व्यवहार में, "प्रोग्राम का भाग" स्रोत कोड (टेक्स्ट का क्षेत्र) के एक हिस्से को संदर्भित करता है, और इसे लेक्सिकल स्कोप के रूप में जाना जाता है। हालांकि, कुछ भाषाओं में, प्रोग्राम का भाग कार्यावधि(निष्पादन कंप्यूटिंग के दौरान समय अवधि) के एक हिस्से को संदर्भित करता है, और इसे डायनेमिक स्कोप के रूप में जाना जाता है। ये दोनों शब्द कुछ हद तक भ्रामक हैं - वे तकनीकी नियमों का दुरुपयोग करते हैं, जैसा कि परिभाषा में चर्चा की गई है - लेकिन भेद स्वयं सटीक और एकदम सही है, और ये मानक संबंधित शब्द हैं। लेक्सिकल स्कोप इस लेख का मुख्य केंद्रबिन्दु है, डायनेमिक स्कोप को लेक्सिकल स्कोप के विपरीत समझा जाता है।
ज्यादातर दशाओं में, लेक्सिकल स्कोप पर आधारित नाम वियोजन उपयोग करने और लागू करने के लिए अपेक्षाकृत सरल है, क्योंकि उपयोग में कोई व्यक्ति स्रोत कोड में पीछे की ओर पढ़ सकता है, यह निर्धारित करने के लिए कि किस इकाई को एक नाम संदर्भित करता है, और प्रोग्रामिंग भाषा कार्यान्वयन में प्रोग्राम को संकलन या विवेचन करते समय नाम और संदर्भ कोई नामों की एक सूची बनाए रख सकता है। नेम मास्किंग, आगे की डिक्लेरेशन और होइस्टिंग में कठिनाइयाँ उत्पन्न होती हैं, जबकि विशेष रूप से क्लोजर में गैर-स्थानीय वेरिएबल के साथ काफी सूक्ष्मताएँ उत्पन्न होती हैं।
परिभाषा
एक नाम(आइडेंटीफायर) के (लेक्सिकल) "स्कोप" की सख्त परिभाषा स्पष्ट है: लेक्सिकल स्कोप "स्रोत कोड का वह भाग है जिसमें एक इकाई के साथ एक नाम का बाइंडिंग लागू होती है। यह एल्गोल 60 के विनिर्देशन में इसकी 1960 की परिभाषा से वस्तुतः अपरिवर्तित है। प्रतिनिधि भाषा विनिर्देशों का पालन करें:
- एल्गोल 60 (1960)[1]
- निम्न प्रकार की मात्राएँ प्रतिष्ठित हैं: सरल वेरिएबल, ऐरे, लेबल, स्विच और प्रोसीजर्स। स्कोप की मात्रा वर्णन और स्टेटमेंट्स का समूह है जिसमें उस मात्रा से जुड़े आइडेंटीफायर की डिक्लेरेशन मान्य है।
- सी (प्रोग्रामिंग भाषा) (2007)[2]
- एक आइडेंटीफायर किसी ऑब्जेक्ट को निरूपित कर सकता है; एक फंक्शन; एक टैग या स्ट्रक्चर का सदस्य, यूनियन, या इनुमेरशन; एक टाइपिफ़ नाम; एक लेबल नाम; एक मैक्रो नाम; या एक मैक्रो पैरामीटर। एक ही आइडेंटीफायर प्रोग्राम में विभिन्न बिंदुओं पर विभिन्न एंटिटी(संस्थाओं) को निरूपित कर सकता है। [...] प्रत्येक अलग इकाई के लिए जिसे एक आइडेंटीफायर निर्दिष्ट करता है, आइडेंटीफायर दिखाई देता है(अर्थात, इसका उपयोग किया जा सकता है) केवल प्रोग्राम टेक्स्ट के एक क्षेत्र के भीतर जिसे इसका स्कोप कहा जाता है।
- गो (प्रोग्रामिंग भाषा) (2013)[3]
- एक डिक्लेरेशन(घोषणा) एक गैर-खाली आइडेंटीफायर को एक स्थिर, प्रकार, वेरिएबल, फ़ंक्शन, लेबल या पैकेज से बांधती है। [...] एक डिक्लेअर आइडेंटीफायर का स्कोप स्रोत टेक्स्ट की सीमा है जिसमें आइडेंटीफायर निर्दिष्ट स्थिरांक, प्रकार, वेरिएबल, फ़ंक्शन, लेबल या पैकेज को दर्शाता है।
प्रायः स्कोप से तात्पर्य तब होता है जब कोई दिया गया नाम किसी दिए गए वेरिएबल को संदर्भित कर सकता है - जब एक डिक्लेरेशन का प्रभाव होता है - लेकिन यह अन्य इकाइयों पर भी लागू हो सकता है, जैसे कि फ़ंक्शन, प्रकार, क्लास, लेबल, कांस्टेंट और इनुमेरशन।
लेक्सिकल स्कोप बनाम डायनेमिक स्कोप
स्कोप में एक मूलभूत अंतर यह है कि किसी "प्रोग्राम खंड" का क्या मतलब है। लेक्सिकल स्कोप(जिसे स्टैटिक स्कोप भी कहा जाता है) वाली भाषाओं में, नाम रिज़ॉल्यूशन स्रोत कोड और लेक्सिकल संदर्भ(जिसे स्टेटिक संदर्भ भी कहा जाता है) में स्थान पर निर्भर करता है, जिसे नामित वेरिएबल द्वारा परिभाषित किया गया है या कार्य परिभाषित किया गया है। इसके विपरीत, डायनेमिक स्कोप वाली भाषाओं में नाम का समाधान प्रोग्राम की स्थिति पर निर्भर करता है जब नाम का सामना किया जाता है जो एक्सेक्यूशन संदर्भ(जिसे रनटाइम संदर्भ, कॉलिंग संदर्भ या डायनेमिक संदर्भ भी कहा जाता है) द्वारा निर्धारित किया जाता है। व्यवहार में, शाब्दिक स्कोप के साथ स्थानीय लेक्सिकल संदर्भकी खोज करके एक नाम का समाधान किया जाता है, फिर यदि वह विफल हो जाता है, तो बाहरी लेक्सिकल संदर्भ की खोज करके, और इसी तरह; जबकि डायनेमिक स्कोप के साथ, स्थानीय एक्सेक्यूशन संदर्भ को खोजकर एक नाम का समाधान किया जाता है, फिर यदि वह विफल हो जाता है, तो बाहरी एक्सेक्यूशन संदर्भ की खोज करके, और इसी तरह, कॉल स्टैक को आगे बढ़ाया जाता है।[4]
अधिकांश आधुनिक भाषाएं वेरिएबल और फ़ंक्शन के लिए लेक्सिकल स्कोप का उपयोग करती हैं, हालांकि डायनेमिक स्कोप का उपयोग कुछ भाषाओं में किया जाता है, विशेष रूप से लिस्प की कुछ बोलियों, कुछ "लिपिन्यास " भाषाओं और कुछ आदर्श भाषाओं में। [lower-alpha 3] पर्ल 5 लेक्सिकल और डायनेमिक स्कोप दोनों प्रदान करता है। यहां तक कि लेक्सिकल रूप से स्कोप वाली भाषाओं में, बंद करने का स्कोप असंबद्ध लोगों के लिए भ्रमित करने वाली हो सकती है,[citation needed] क्योंकि ये लेक्सिकल संदर्भपर निर्भर करते हैं जहां क्लोजर को परिभाषित किया गया है, न कि जहां इसे कहा जाता है।
लेक्सिकल रिज़ॉल्यूशन को संकलन समय पर निर्धारित किया जा सकता है, और इसे आरंभी बाइंडिंग के रूप में भी जाना जाता है, जबकि डायनेमिक रिज़ॉल्यूशन को सामान्य रूप से केवल रन टाइम (प्रोग्राम जीवनचक्र वेरिएबल) पर निर्धारित किया जा सकता है, और इस प्रकार इसे विलंब बाइंडिंग के रूप में जाना जाता है।
संबंधित अवधारणाएं
ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग में, डायनेमिक प्रेषण रनटाइम पर एक ऑब्जेक्ट विधि का चयन करता है, हालांकि वास्तविक नेम बाइंडिंग संकलन समय पर किया जाता है या कार्यावधि भाषा पर निर्भर करता है। मैक्रो में डी फैक्टो डायनेमिक स्कोप सामान्य है, जो सीधे नाम रिज़ॉल्यूशन नहीं करते हैं, बल्कि जगह में विस्तार करते हैं।
एंगुलर जे एस जैसे कुछ प्रोग्रामिंग फ्रेमवर्क इस लेख में उपयोग किए जाने वाले तरीके से पूरी तरह से अलग अर्थ के लिए स्कोप शब्द का उपयोग करते हैं। उन रूपरेखाओं में स्कोप केवल प्रोग्रामिंग भाषा का एक ऑब्जेक्ट है जिसका वे उपयोग करते हैं (एंगुलरजेएस के मामले में जावास्क्रिप्ट) जिसका प्रयोग ढांचे द्वारा कुछ तरीकों से डायनेमिक स्कोप का अनुकरण करने के लिए किया जाता है जो इसके वेरिएबल के लिए व्याख्यात्मक स्कोप का उपयोग करता है। वे एंगुलर जे एस प्रोग्राम के किसी भी भाग में, किसी अन्य ऑब्जेक्ट की तरह भाषा के वेरिएबल स्कोप के सामान्य नियमों का पालन करते हुए, और अपने स्वयं के इनहेरिटेंस और ट्रांसक्लुजन नियम का उपयोग करते हुए, स्वयं संदर्भ में हो सकते या संदर्भ में नहीं हो सकते(शब्द के सामान्य अर्थ का उपयोग करके) हैं। एंगुलर जे एस के संदर्भ में, कभी-कभी भ्रम से बचने के लिए $स्कोप (डॉलर चिह्न के साथ) शब्द का उपयोग किया जाता है, लेकिन वेरिएबल नामों में डॉलर चिह्न का उपयोग प्रायः शैली मार्गदर्शक द्वारा हतोत्साहित किया जाता है।[5]
प्रयोग
स्कोप नाम रिज़ॉल्यूशन का एक महत्वपूर्ण घटक है,[lower-alpha 4] जो बदले में प्रोग्रामिंग भाषाओं के औपचारिक शब्दार्थ के लिए मौलिक है। नाम रिज़ॉल्यूशन(स्कोप सहित) प्रोग्रामिंग भाषाओं के बीच भिन्न होता है, और प्रोग्रामिंग भाषा के भीतर, इकाई के प्रकार से भिन्न होता है; स्कोप के नियमों को स्कोप नियम (या स्कोपिंग नियम) कहा जाता है। वैकल्पिक् प्रोग्रामिंग में नामस्थान के साथ, स्कोप नियम महत्वपूर्ण हैं, इसलिए प्रोग्राम के एक हिस्से में बदलाव एक असंबंधित हिस्से को नहीं तोड़ता है।
समीक्षा
स्कोप पर चर्चा करते समय, तीन बुनियादी अवधारणाएँ होती हैं: स्कोप, परिक्षेप और संदर्भ। विशेष रूप से स्कोप और संदर्भ प्रायः भ्रमित होते हैं: स्कोप एक नेम बाइंडिंग की संपत्ति है, जबकि संदर्भ प्रोग्राम के एक भाग की संपत्ति है, जो या तो स्रोत कोड का एक भाग है (लेक्सिकल संदर्भ या स्थिर संदर्भ) या कार्यावधि का एक भाग (प्रोग्राम जीवन चक्र वेरिएबल) (निष्पादन संदर्भ, कार्यावधि संदर्भ, कॉलिंग संदर्भ या डायनेमिक संदर्भ)। निष्पादन संदर्भ में लेक्सिकल संदर्भ (वर्तमान निष्पादन बिंदु पर) और अतिरिक्त कार्यावधि स्थिति जैसे कॉल स्टैक निहित हैं।[lower-alpha 5] कड़ाई से बोलते हुए, निष्पादन के दौरान एक प्रोग्राम विभिन्न नेम बाइंडिंग के स्कोप में प्रवेश करता है और बाहर निकलता है, और निष्पादन के एक बिंदु पर नेम बाइंडिंग संदर्भ में है या संदर्भ में नहीं है, इसलिए नेम बाइंडिंग संदर्भ में आती है या संदर्भ से बाहर हो जाती है क्योंकि प्रोग्राम निष्पादन प्रवेश करता है या बाहर निकलता है।[lower-alpha 6] हालाँकि, व्यवहार में उपयोग बहुत कम है।
स्कोप एक स्रोत-कोड स्तर की अवधारणा है, और नेम बाइंडिंग का एक गुण धर्म है, विशेष रूप से वेरिएबल या फ़ंक्शन नेम बाइंडिंग - स्रोत कोड में नाम प्रोग्राम में संस्थाओं के लिए संदर्भ हैं - और एक भाषा के कम्पाइलर या अनुवादक के व्यवहार का भाग है। जैसे, स्कोप के विषय पॉइंटर्स के समान होते हैं, जो एक प्रकार का संदर्भ है जो प्रायः प्रोग्रामों में उपयोग किया जाता है। एक वेरिएबल के मान का उपयोग करना जब नाम संदर्भ में है, लेकिन वेरिएबल अप्रारंभीकृत है, एक वाइल्ड पॉइंटर को अपसंदर्भन(मूल्य तक पहुँचने) के अनुरूप है, क्योंकि यह अपरिभाषित है। हालाँकि, जब तक वे संदर्भ से बाहर नहीं जाते, तब तक वेरिएबल नष्ट नहीं होते हैं, डैंगलिंग पॉइंटर का समधर्मी विद्यमान नहीं होता है।
वैरिएबल जैसी इकाइयों के लिए, स्कोप जीवनकाल का एक उपवर्ग है (जिसे एक्सटेंट के रूप में भी जाना जाता है) - एक नाम केवल एक वेरिएबल को संदर्भित कर सकता है जो विद्यमान है (संभवतः अपरिभाषित मान के साथ), लेकिन विद्यमान वेरिएबल्स नहीं हैं आवश्यक रूप से दृश्यमान: एक वेरिएबल विद्यमान हो सकता है लेकिन अप्राप्य हो सकता है (मान संग्रहीत है लेकिन किसी दिए गए संदर्भ में संदर्भित नहीं है), या सुलभ है लेकिन दिए गए नाम के माध्यम से नहीं है, जिस स्थिति में यह संदर्भ में नहीं है (प्रोग्राम स्कोप से बाहर है)। अन्य स्थितियों में "जीवनकाल" अप्रासंगिक है - एक लेबल (स्रोत कोड में नाम की स्थिति) प्रोग्राम के साथ आजीवन समान है (सांख्यिकीय रूप से संकलित भाषाओं के लिए), लेकिन संदर्भ में हो सकता है या प्रोग्राम में दिए गए बिंदु पर नहीं हो सकता है, और इसी तरह स्थिर वेरिएबल के लिए —एक स्थिर वैश्विक वेरिएबल पूरे प्रोग्राम के संदर्भ में है, जबकि एक स्थिर स्थानीय वेरिएबल केवल एक फंक्शन या अन्य स्थानीय संदर्भ के संदर्भ में है, लेकिन दोनों के पास प्रोग्राम के पूरे प्रवाह का जीवनकाल है।
यह निर्धारित करना कि किस इकाई का नाम संदर्भित है, नाम वियोजन या नेम बाइंडिंग (विशेष रूप से ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग में) के रूप में जाना जाता है, और भाषाओं के बीच भिन्न होता है। एक नाम दिया गया है, भाषा (उचित ढंग से, कम्पाइलर या अनुवादक) उन सभी इकाइयों की जाँच करती है जो सुमेलन के संदर्भ में हैं; अस्पष्टता के मामले में (एक ही नाम वाली दो इकाइयाँ, जैसे कि एक ही नाम के साथ एक वैश्विक और स्थानीय वेरिएबल), उन्हें अलग करने के लिए नाम वियोजन नियमों का उपयोग किया जाता है। सबसे अधिक बार, नाम वियोजन "आंतरिक-से-बाहरी" संदर्भ नियम पर निर्भर करता है, जैसे कि पायथन एलईजीबी (लोकल, एनक्लोजिंग, ग्लोबल, बिल्ट-इन) नियम: नाम निहित रूप से सबसे कम प्रासंगिक संदर्भ को हल करता है। कुछ स्थितियों में नाम संकल्प स्पष्ट रूप से निर्दिष्ट किया जा सकता है, जैसे कि द्वारा सार्वभौम(ग्लोबल)
और विस्थानीय(नॉनलोकल)
पायथन में कीवर्ड; अन्य स्थितियों में मूल नियमों को अधिरोहित नहीं किया जा सकता है।
जब दो समान नाम एक ही समय में संदर्भ में होते हैं, विभिन्न संस्थाओं का जिक्र करते हुए, एक कहता है कि नेम मास्किंग हो रहा है, जहां उच्च-प्राथमिकता वाला नाम (प्रायः अंतरतम) निम्न-प्राथमिकता वाले नाम को मास्क कर रहा है। वेरिएबल के स्तर पर, इसे वेरिएबल छायांकन के रूप में जाना जाता है। मास्किंग से तार्किक त्रुटियों की संभावना के कारण, कुछ भाषाएँ मास्किंग को अस्वीकार या हतोत्साहित करती हैं, त्रुटि उत्पन्न करती हैं या संकलन समय या कार्यावधि समय (रन टाइम) पर चेतावनी देती हैं।
विभिन्न प्रोग्रामिंग भाषाओं में विभिन्न प्रकार की डिक्लेरेशन और नामों के लिए विभिन्न स्कोप के नियम हैं। इस तरह के स्कोप के नियमों का प्रोग्रामिंग भाषाओं के औपचारिक शब्दार्थ पर और इसके परिणामस्वरूप, प्रोग्रामों के व्यवहार और शुद्धता पर बड़ा प्रभाव पड़ता है। C++ जैसी भाषाओं में, एक अनबंधी वेरिएबल तक पहुँचने के लिए अच्छी तरह से परिभाषित शब्दार्थ नहीं होता है और इसके परिणामस्वरूप अपरिभाषित व्यवहार हो सकता है, जो डैंगलिंग पॉइंटर के संदर्भ में होता है; और उनके स्कोप से बाहर उपयोग की जाने वाली डिक्लेरेशन या नाम रचनाक्रम(सिंटैक्स) त्रुटियां उत्पन्न करेंगे।
स्कोप प्रायः अन्य भाषा निर्माणों से बंधे होते हैं और निहित रूप से निर्धारित होते हैं, लेकिन कई भाषाएँ विशेष रूप से स्कोप को नियंत्रित करने के लिए भी निर्माण की पेशकश करती हैं।
स्कोप का स्तर
स्कोप एक कम से कम एक व्यंजक से लेकर, बीच में कई संभावित श्रेणी के साथ पूरे प्रोग्राम तक भिन्न हो सकता है। सबसे सरल स्कोप नियम वैश्विक स्कोप है—पूरे प्रोग्राम में सभी निकाय दिखाई देते हैं। सबसे बुनियादी वैकल्पिक् स्कोप नियम दो-स्तरीय स्कोप है, प्रोग्राम में कहीं भी वैश्विक स्कोप और फ़ंक्शन के भीतर स्थानीय स्कोप होता है। अधिक परिष्कृत वैकल्पिक् प्रोग्रामिंग एक अलग वैकल्पिक् स्कोप की अनुमति देता है, जहां इकाई के भीतर नाम दिखाई देते हैं (इकाई के लिए निजी) लेकिन इसके बाहर दिखाई नहीं देते। किसी फ़ंक्शन के भीतर, कुछ भाषाएँ, जैसे कि C, ब्लॉक स्कोप को किसी फ़ंक्शन के उपवर्ग तक सीमित करने की अनुमति देती हैं; अन्य, विशेष रूप से कार्यात्मक भाषाएं, एक एक्सप्रेशन के स्कोप को प्रतिबंधित करने के लिए एक्सप्रेशन के स्कोप की अनुमति देती हैं। अन्य स्कोप में फ़ाइल स्कोप (विशेष रूप से C में) निहित है जो इकाई स्कोप के समान व्यवहार करता है, और फ़ंक्शंस के बाहर ब्लॉक स्कोप (विशेष रूप से पर्ल में) होता है।
एक सूक्ष्म मुद्दा ठीक उसी समय होता है जब कोई स्कोप शुरू और समाप्त होता है। कुछ भाषाओं में, जैसे सी, एक नाम का स्कोप नाम की डिक्लेरेशन से शुरू होता है, और इस प्रकार किसी दिए गए खण्ड में डिक्लेअर अलग-अलग नामों के अलग-अलग स्कोप हो सकते हैं। इसके लिए उपयोग से पहले कार्यों को डिक्लेअर करने की आवश्यकता होती है, हालांकि जरूरी नहीं कि उन्हें परिभाषित किया जाए, और कुछ स्थितियों में विशेष रूप से पारस्परिक पुनरावृत्ति के लिए आगे की डिक्लेरेशन की आवश्यकता होती है। अन्य भाषाओं में, जैसे कि पायथन, एक नाम का स्कोप प्रासंगिक खण्ड के आरंभ में शुरू होता है जहां नाम डिक्लेअर किया जाता है (जैसे कि फ़ंक्शन की आरंभ), चाहे वह कहीं भी परिभाषित हो, इसलिए किसी दिए गए खण्ड के सभी नामों में एक ही स्कोप होता है। जावास्क्रिप्ट में, डिक्लेअर नाम का स्कोप let
या const
नाम की डिक्लेरेशन से शुरू होता है, और डिक्लेअर नाम का स्कोप var
फंक्शन के प्रारंभ में शुरू होता है जहां नाम डिक्लेअर किया जाता है, जिसे वेरिएबल होइस्टिंग के रूप में जाना जाता है। अपरिभाषित मान वाले संदर्भ में नामों का व्यवहार भिन्न होता है: पायथन में अपरिभाषित नामों के उपयोग से रनटाइम त्रुटि उत्पन्न होती है, जबकि जावास्क्रिप्ट में अपरिभाषित नामों के साथ डिक्लेअर किया जाता है var
पूरे फंक्शन में प्रयोग करने योग्य हैं क्योंकि वे निहित रूप से अपरिभाषित मूल्य के लिए बाध्य हैं।
एक्सप्रेशन का स्कोप
नेम बाइंडिंग का स्कोप एक एक्सप्रेशन है, जिसे एक्सप्रेशन स्कोप के नाम से जाना जाता है। एक्सप्रेशन का स्कोप कई भाषाओं में उपलब्ध है, विशेष रूप से कार्यात्मक प्रोग्रामिंग भाषाएं जो लेट-एक्सप्रेशन नामक सुविधा प्रदान करती हैं, जिससे डिक्लेरेशन का स्कोप एकल एक्सप्रेशन हो जाता है। यह सुविधाजनक है अगर, उदाहरण के लिए, गणना के लिए एक मध्यवर्ती मान की आवश्यकता होती है। उदाहरण के लिए, मानक एमएल में, यदि f()
रिटर्न 12
, तब let val x = f() in x * x end
एक एक्सप्रेशन है जो 144 का
मूल्यांकन करती है , x
नाम के एक अस्थायी वेरिएबल का उपयोग करते हुएf()
दो बार कॉल करने से बचने के लिए करती है। ब्लॉक स्कोप वाली कुछ भाषाएँ एक एक्सप्रेशन में सन्निहित किए जाने वाले ब्लॉक के लिए सिंटैक्स की पेशकश करके इस कार्यक्षमता का अनुमान लगाती हैं; उदाहरण के लिए, उपर्युक्त मानक एमएल एक्सप्रेशन पर्ल में do { my $x = f(); $x * $x }
, या GNU कंपाइलर संग्रह में ({ int x = f(); x * x; })
के रूप में।
पायथन में, जेनरेटर एक्सप्रेशंस और लिस्ट कॉम्प्रिहेंशन (पायथन 3 में) में सहायक वेरिएबल्स में एक्सप्रेशन स्कोप होता है।
सी में, फ़ंक्शन प्रोटोटाइप में वेरिएबल नामों में एक्सप्रेशन का स्कोप होता है, जिसे इस संदर्भ में फ़ंक्शन प्रोटोकॉल स्कोप के रूप में जाना जाता है। जैसा कि प्रोटोटाइप में वेरिएबल नामों को संदर्भित नहीं किया जाता है (वे वास्तविक परिभाषा में भिन्न हो सकते हैं) - वे सिर्फ प्रतिरूप हैं - इन्हें प्रायः छोड़ दिया जाता है, हालांकि उनका उपयोग उदाहरण के लिए प्रलेखन बनाने के लिए किया जा सकता है।
ब्लॉक स्कोप
नेम बाइंडिंग का स्कोप एक ब्लॉक है, जिसे ब्लॉक स्कोप के रूप में जाना जाता है। ब्लॉक का स्कोप कई स्कोप में उपलब्ध है, लेकिन सभी में नहीं, ब्लॉक-संरचित प्रोग्रामिंग भाषाओं में उपलब्ध है। यह एल्गोल 60 के साथ शुरू हुआ, जहां [ई]वरी डिक्लेरेशन... केवल उस ब्लॉक के लिए मान्य है। ,[6] और आज विशेष रूप से पास्कल और सी परिवारों और परंपराओं में भाषाओं से जुड़ा हुआ है। प्रायः यह ब्लॉक एक फ़ंक्शन के भीतर समाहित होता है, इस प्रकार एक फ़ंक्शन के एक भाग के स्कोप को सीमित करता है, लेकिन कुछ स्थितियों में, जैसे कि पर्ल, ब्लॉक फ़ंक्शन के भीतर नहीं हो सकता है।
unsigned int sum_of_squares(const unsigned int N) {
unsigned int ret = 0;
for (unsigned int n = 1; n <= N; n++) { const unsigned int n_squared = n * n;
ret += n_squared;
}
return ret;
}
ब्लॉक स्कोप के उपयोग का एक प्रतिनिधि उदाहरण यहां दिखाया गया सी कोड है, जहां दो वेरिएबल लूप के स्कोप में हैं: लूप वेरिएबल n, जिसे एक बार प्रारंभ किया जाता है और लूप के प्रत्येक पुनरावृत्ति पर बढ़ाया जाता है, और सहायक वेरिएबल n_squared, जो प्रत्येक पुनरावृत्ति पर आरंभीकृत होता है। उद्देश्य फ़ंक्शन स्कोप में वेरिएबल जोड़ने से बचना है जो केवल एक विशेष ब्लॉक के लिए प्रासंगिक हैं - उदाहरण के लिए, यह उन त्रुटियों को रोकता है जहां सामान्य लूप वेरिएबल i को गलती से पहले से ही किसी अन्य मान पर निर्धारित कर दिया गया है। इस उदाहरण में एक्सप्रेशन n * n
प्रायः एक सहायक वेरिएबल को नहीं सौंपा जाएगा, और लूप का ढ़ाँचा बस लिखा जाएगा, ret += n * n
लेकिन अधिक जटिल उदाहरणों में सहायक वेरिएबल उपयोगी होते हैं।
ब्लॉक मुख्य रूप से नियंत्रण प्रवाह के लिए उपयोग किए जाते हैं, जैसे कि इफ, वाहील, और फॉर लूप के लिए और इन स्थितियों में ब्लॉक स्कोप का मतलब है कि वेरिएबल का स्कोप किसी फ़ंक्शन के निष्पादन के प्रवाह की संरचना पर निर्भर करता है। हालाँकि, ब्लॉक स्कोप वाली भाषाएँ प्रायः नग्न ब्लॉकों के उपयोग की अनुमति देती हैं, जिनका एकमात्र उद्देश्य वेरिएबल स्कोप के ठीक-ठाक नियंत्रण की अनुमति देना है। उदाहरण के लिए, एक सहायक वेरिएबल को एक ब्लॉक में परिभाषित किया जा सकता है, फिर उपयोग किया जाता है (जैसे, फ़ंक्शन स्कोप के साथ एक वेरिएबल में जोड़ा जाता है) और ब्लॉक समाप्त होने पर छोड़ दिया जाता है, या थोड़ी देर के लूप को एक ब्लॉक में संलग्न किया जा सकता है जो लूप के अंदर उपयोग किए जाने वाले वेरिएबल को आरंभ करता है। जिसे केवल एक बार प्रारंभ किया जाना चाहिए।
कई प्रोग्रामिंग भाषाओं की एक सूक्ष्मता, जैसे अल्गोल 68 और सी (इस उदाहरण में प्रदर्शित और सी 99 के बाद से मानकीकृत), यह है कि ब्लॉक-स्कोप वेरिएबल न केवल ब्लॉक के ढाँचे के भीतर, बल्कि नियंत्रण कथन के भीतर भी डिक्लेअर किए जा सकते हैं। यह फ़ंक्शन पैरामीटर के अनुरूप है, जो फ़ंक्शन डिक्लेरेशन(फ़ंक्शन ढाँचे के ब्लॉक शुरू होने से पहले) में डिक्लेअर किया गया है, और पूरे फ़ंक्शन ढाँचे के स्कोप में है। यह मुख्य रूप से लूप के लिए उपयोग किया जाता है, जिसमें लूप की स्थिति से अलग एक प्रारंभन स्टेटमेंट होता है, वाहील लूप के विपरीत, और यह एक सामान्य इडियम है।
सैडोविंग के लिए ब्लॉक स्कोप का उपयोग किया जा सकता है। इस उदाहरण में, ब्लॉक के अंदर सहायक वेरिएबल को n भी कहा जा सकता था, जो पैरामीटर नाम को शैडो करता है, लेकिन त्रुटियों की संभावना के कारण इसे खराब ढंग माना जाता है। इसके अलावा, सी के कुछ वंशज, जैसे कि जावा और सी #, ब्लॉक स्कोप के लिए समर्थन होने के बावजूद (जिसमें एक स्थानीय वेरिएबल को फ़ंक्शन के अंत से पहले संदर्भ से बाहर जाने के लिए बनाया जा सकता है), एक स्थानीय वेरिएबल को दूसरे को छिपाने की अनुमति न दें . ऐसी भाषाओं में, दूसरे n की डिक्लेरेशन के प्रयास के परिणामस्वरूप सिंटैक्स त्रुटि होगी, और n वेरिएबलों में से एक का नाम बदलना होगा।
यदि किसी ब्लॉक का उपयोग किसी वेरिएबल के मान को निर्धारित करने के लिए किया जाता है, तो ब्लॉक स्कोप के लिए आवश्यक है कि वेरिएबल को ब्लॉक के बाहर डिक्लेअर किया जाए। यह एकल असाइनमेंट के साथ सशर्त बयानों के उपयोग को जटिल बनाता है। उदाहरण के लिए, पायथन में, जो ब्लॉक स्कोप का उपयोग नहीं करता है, एक वैरिएबल को इस तरह से आरंभ कर सकता है:
if c:
a = "foo"
else:
a = ""
जहाँ if
स्टेटमेंट के बादa
तक पहुँचा जा सकता है।
पर्ल में, जिसमें ब्लॉक स्कोप है, इसके बजाय ब्लॉक से पहले वेरिएबल डिक्लेअर करने की आवश्यकता है:
my $a;
if (c) {
$a = 'foo';
} else {
$a = ' ';
}
इसके बजाय प्रायः इसे एकाधिक असाइनमेंट का उपयोग करके फिर से लिखा जाता है, वेरिएबल को पूर्व निर्धारित मान पर प्रारंभ किया जाता है। पायथन में (जहां यह आवश्यक नहीं है) यह होगा:
a = " "
if c:
a = "foo"
जबकि पर्ल में यह होगा:
my $a = ' ';
if (c) {
$a = 'foo';
}
एकल वेरिएबल असाइनमेंट के मामले में, एक विकल्प एक ब्लॉक से बचने के लिए टर्नरी ऑपरेटर का उपयोग करना है, लेकिन यह सामान्य रूप से कई वेरिएबल असाइनमेंट के लिए संभव नहीं है, और जटिल तर्क के लिए पढ़ना मुश्किल है।
यह C में एक अधिक महत्वपूर्ण मुद्दा है, विशेष रूप से स्ट्रिंग असाइनमेंट के लिए, क्योंकि स्ट्रिंग प्रारंभन स्वचालित रूप से मेमोरी आवंटित कर सकता है, जबकि स्ट्रिंग असाइनमेंट को पहले से ही आरंभिक वेरिएबल के लिए मेमोरी आवंटित करने, एक स्ट्रिंग कॉपी और जाँचने की आवश्यकता होती है कि ये सफल हैं।
कुछ भाषाएं ब्लॉक स्कोप की अवधारणा को एक फ़ंक्शन के बाहर अलग-अलग परिक्षेप तक लागू करने की अनुमति देती हैं। उदाहरण के लिए, पर्ल स्निपेट में दाईं ओर, $counter
ब्लॉक स्कोप के साथ एक वेरिएबल नाम है (के उपयोग के कारण my
कीवर्ड), जबकि increment_counter
वैश्विक स्कोप वाला एक फ़ंक्शन नाम है। प्रत्येक कॉल करने के लिए increment_counter,
$counter
के मान में एक की वृद्धि करेगा, और नया मान रिटर्न करेगा। इस ब्लॉक के बाहर का कोड increment_counter
को कॉल कर सकता है , लेकिन अन्यथा $counter
का मान प्राप्त या परिवर्तित नहीं कर सकता . यह इडियम पर्ल में क्लोजर को परिभाषित करने की अनुमति देता है।
{
my $counter = 0;
sub increment_counter {
return ++$counter;
}
}
फ़ंक्शन स्कोप
जब किसी फ़ंक्शन के भीतर डिक्लेअर वेरिएबल का स्कोप उस फ़ंक्शन से आगे नहीं बढ़ता है, तो इसे फ़ंक्शन स्कोप के रूप में जाना जाता है।[7] फ़ंक्शन स्कोप अधिकांश प्रोग्रामिंग भाषाओं में उपलब्ध है जो फ़ंक्शन या सबरूटीन में एक स्थानीय वेरिएबल बनाने का एक तरीका प्रदान करते हैं: एक वेरिएबल जिसका स्कोप समाप्त होता है (जो संदर्भ से बाहर हो जाता है) जब फ़ंक्शन रिटर्न करता है। ज्यादातर स्थितियों में वेरिएबल का जीवनकाल फ़ंक्शन कॉल की अवधि है - यह एक स्वचालित वेरिएबल है, जब फ़ंक्शन शुरू होता है (या वेरिएबल डिक्लेअर किया जाता है), फ़ंक्शन के रिटर्न आने पर नष्ट हो जाता है - जबकि वेरिएबल का स्कोप अंदर होता है , हालांकि भीतर का अर्थ इस बात पर निर्भर करता है कि स्कोप लेक्सिकल या डायनेमिक है या नहीं। हालाँकि, कुछ भाषाएँ, जैसे C, स्थैतिक स्थानीय वेरिएबल भी प्रदान करती हैं, जहाँ वेरिएबल का जीवनकाल प्रोग्राम का संपूर्ण जीवनकाल होता है, लेकिन वेरिएबल केवल संदर्भ में होता है जब फ़ंक्शन के अंदर होता है। स्थैतिक स्थानीय वेरिएबल के मामले में, वेरिएबल तब बनाया जाता है जब प्रोग्राम आरंभ होता है, और केवल तभी नष्ट हो जाता है जब प्रोग्राम समाप्त हो जाता है, जैसा कि एक स्थिर वैश्विक वेरिएबल के साथ होता है, लेकिन केवल एक स्वचालित स्थानीय वेरिएबल की तरह एक फ़ंक्शन के संदर्भ में होता है।
महत्वपूर्ण रूप से, लेक्सिकल स्कोप में फंक्शन स्कोप के साथ एक वेरिएबल का स्कोप केवल फंक्शन के लेक्सिकल संदर्भ में होता है: यह संदर्भ से बाहर हो जाता है जब फ़ंक्शन के भीतर किसी अन्य फ़ंक्शन को कॉल किया जाता है, और फ़ंक्शन के रिटर्न आने पर संदर्भ में रिटर्न आ जाता है - कॉल्ड फंक्शन्स के पास स्थानीय वेरिएबल्स के कालिंग फंक्शन्स का अभिगम नहीं है, और स्थानीय वेरिएबल केवल उस फ़ंक्शन के ढांचे के संदर्भ में होते हैं जिसमें उन्हें डिक्लेअर किया जाता है। इसके विपरीत, डायनेमिक स्कोप में, स्कोप फ़ंक्शन के निष्पादन संदर्भ तक विस्तारित होता है: स्थानीय वेरिएबल तब संदर्भ में रहते हैं जब किसी अन्य फ़ंक्शन को कॉल किया जाता है, केवल संदर्भ से बाहर जाना जब परिभाषित फ़ंक्शन समाप्त होता है, और इस प्रकार स्थानीय वेरिएबल फ़ंक्शन के संदर्भ में होते हैं। जिसमें उन्हें परिभाषित किया गया है और सभी को फंक्शन कहा जाता है। लेक्सिकल स्कोप और नेस्टेड फ़ंक्शंस वाली भाषाओं में, नेस्टेड फ़ंक्शंस के लिए स्थानीय वेरिएबल संदर्भ में हैं, क्योंकि ये समान लेक्सिकल संदर्भ में हैं, लेकिन अन्य फ़ंक्शंस के लिए नहीं हैं जो लेक्सिकल रूप से नेस्टेड नहीं हैं। एक संलग्न फ़ंक्शन के स्थानीय वेरिएबल को नेस्टेड फ़ंक्शन के लिए गैर-स्थानीय वेरिएबल के रूप में जाना जाता है। फ़ंक्शन का स्कोप एनोनिमस फ़ंक्शंस पर भी लागू होता है।
def square(n):
return n * n def sum_of_squares(n): total = 0 i = 0 while i <= n: total += square(i) i += 1 return total
उदाहरण के लिए, दाईं ओर पायथन कोड के भाग में, दो फंक्शन्स square
और sum_of_squares
को परिभाषित किया गया है। square
किसी संख्या के वर्ग की गणना करता है; sum_of_squares
किसी संख्या तक सभी वर्गों के योग की गणना करता है। (उदाहरण के लिए, square(4)
4 है2 =16
, और sum_of_squares(4)
0 है2 + 12 + 22 + 32 + 42 =30
.)
इनमें से प्रत्येक फ़ंक्शन में n नाम का एक वेरिएबल है जो फ़ंक्शन के तर्क का प्रतिनिधित्व करता है। ये दो n वेरिएबल पूरी तरह से अलग और असंबंधित हैं, एक ही नाम होने के बावजूद, क्योंकि वे फ़ंक्शन स्कोप के साथ लेक्सिकली स्कोप्ड लोकल वैरिएबल हैं: प्रत्येक का स्कोप अपना, लेक्सिकली अलग फंक्शन है और इस प्रकार, वे ओवरलैप नहीं करते हैं । इसलिए, अपने स्वयं के n को बदले बिना sum_of_squares
square
को कॉल कर सकते हैं। इसी प्रकार, sum_of_squares
total और i नाम के वेरिएबल्स हैं; ये वेरिएबल्स, उनके सीमित स्कोप के कारण, total या i नाम के किसी भी वेरिएबल्स के साथ हस्तक्षेप नहीं करेंगे जो किसी अन्य फ़ंक्शन से संबंधित हो सकते हैं। दूसरे शब्दों में, इन नामों और किसी भी असंबंधित नामों के बीच टकराव का कोई जोखिम नहीं है, भले ही वे समान हों।
कोई नेम मास्किंग नहीं हो रहा है: n नाम का केवल एक वेरिएबल किसी भी समय संदर्भ में है, क्योंकि स्कोप ओवरलैप नहीं होते हैं। इसके विपरीत, डायनेमिक स्कोप वाली भाषा में एक समान टुकड़ा लिखा जाना था, कॉलिंग फ़ंक्शन में n तथाकथित फ़ंक्शन में संदर्भ में रहेगा - स्कोप अतिछादित(ओवरलैप) होगा - कॉल किए गए फ़ंक्शन में नए n द्वारा मास्क("शैडो") किया जाएगा।
फ़ंक्शन स्कोप काफी अधिक जटिल है यदि फ़ंक्शंस प्रथम श्रेणी की ऑब्जेक्ट्स हैं और स्थानीय रूप से किसी फ़ंक्शन में बनाई जा सकती हैं और फिर वापस आ सकती हैं। इस मामले में नेस्टेड फ़ंक्शन में कोई भी वेरिएबल जो इसके लिए स्थानीय नहीं हैं (फ़ंक्शन परिभाषा में अनबाउंड वेरिएबल, जो एक संलग्न संदर्भ में वेरिएबल के लिए हल होते हैं) एक क्लोजर बनाते हैं, न केवल फ़ंक्शन के रूप , बल्कि इसका संदर्भ (वेरिएबलों का) रिटर्न किया जाना चाहिए, और फिर संभावित रूप से एक अलग संदर्भ में बुलाया जाना चाहिए। इसके लिए कम्पाइलर से काफी अधिक समर्थन की आवश्यकता होती है, और यह प्रोग्राम विश्लेषण को जटिल बना सकता है।
फ़ाइल का स्कोप
नेम बाइंडिंग का स्कोप एक फाइल है, जिसे फाइल स्कोप के रूप में जाना जाता है। फ़ाइल का स्कोप काफी हद तक सी (और सी ++) के लिए विशेष है, जहां फ़ाइल के शीर्ष स्तर पर डिक्लेअर वेरिएबल और कार्यों का स्कोप (किसी भी फ़ंक्शन के भीतर नहीं) पूरी फ़ाइल के लिए है - या सी के लिए है, डिक्लेरेशन से अंत तक स्रोत फ़ाइल, या अधिक सटीक रूप से अनुवाद इकाई (आंतरिक लिंकिंग) है। इसे इकाई स्कोप के रूप में देखा जा सकता है, जहां इकाई को फाइलों के साथ पहचाना जाता है, और अधिक आधुनिक भाषाओं में एक स्पष्ट इकाई स्कोप द्वारा प्रतिस्थापित किया जाता है। इनक्लूड स्टेटमेंट्स की उपस्थिति के कारण, जो आंतरिक संदर्भ में वेरिएबल्स और फ़ंक्शंस जोड़ते हैं और स्वयं इनक्लूड स्टेटमेंट्स को कॉल कर सकते हैं, यह निर्धारित करना मुश्किल हो सकता है कि फ़ाइल के मुख्य भाग में संदर्भ में क्या है।
उपरोक्त सी कोड स्निपेट में, फ़ंक्शन का नाम sum_of_squares
फ़ाइल का स्कोप है।
मोडूयल(इकाई) स्कोप
नेम बाइंडिंग का स्कोप एक इकाई है, जिसे इकाई स्कोप के रूप में जाना जाता है। इकाई स्कोप वैकल्पिक् प्रोग्रामिंग में उपलब्ध है जहां मोडूयल (जो विभिन्न फाइलों को फैला सकते हैं) एक जटिल प्रोग्राम की मूल इकाई हैं, क्योंकि वे जानकारी को छिपाने और एक सीमित अंतरापृष्ठ को उजागर करने की अनुमति देते हैं। इकाई स्कोप भाषाओं के मोडुला परिवार में अग्रणी था, और पायथन (जो मोडुला से प्रभावित था) एक निरुपक समकालीन उदाहरण है।
कुछ ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग भाषाओं में, जिनमें इकाई के लिए प्रत्यक्ष समर्थन की कमी होती है, जैसे कि सी ++, एक समान क्लास वर्ग पदानुक्रम द्वारा प्रदान की जाती है, जहां क्लास प्रोग्राम की मूल इकाई होती हैं, और क्लास में निजी विधियां हो सकती हैं। यह नाम संकल्प और स्कोप के बजाय डायनेमिक प्रेषण के संदर्भ में ठीक से समझा जाता है, हालांकि वे प्रायः समान भूमिका निभाते हैं। कुछ स्थितियों में ये दोनों सुविधाएं उपलब्ध हैं, जैसे कि पायथन में, जिसमें इकाई और क्लास दोनों हैं, और कोड संगठन (इकाई-स्तरीय फ़ंक्शन या पारंपरिक रूप से निजी पद्धति के रूप में) प्रोग्रामर की पसंद है।
वैश्विक स्कोप
एक नेम बाइंडिंग का स्कोप एक संपूर्ण प्रोग्राम है, जिसे वैश्विक स्कोप के रूप में जाना जाता है। ग्लोबल स्कोप वाले वेरिएबल नाम- जिन्हें ग्लोबल वेरिएबल कहा जाता है- को प्रायः बुरा व्यवहार माना जाता है, कम से कम कुछ भाषाओं में, नाम टकराव की संभावना और अनजाने में मास्किंग के साथ-साथ खराब मॉड्युलैरिटी, और फंक्शन स्कोप या ब्लॉक स्कोप पर विचार किया जाता है। बेहतर। हालाँकि, ग्लोबल स्कोप का उपयोग प्रायः (भाषा के आधार पर) विभिन्न प्रकार के नामों के लिए किया जाता है, जैसे कि फ़ंक्शंस के नाम, क्लास के नाम (कंप्यूटर प्रोग्रामिंग) और अन्य डेटा प्रकार के नाम। इन स्थितियों में टकराव से बचने के लिए तंत्र जैसे नाम स्थान का उपयोग किया जाता है।
लेक्सिकल स्कोप बनाम डायनेमिक स्कोप
स्थानीय वेरिएबल का उपयोग - सीमित स्कोप वाले वेरिएबल नामों का, जो केवल एक विशिष्ट कार्य के भीतर विद्यमान हैं - दो समान नाम वाले वेरिएबल के बीच नाम टकराव के जोखिम से बचने में मदद करता है। हालाँकि, इस प्रश्न का उत्तर देने के लिए दो अलग-अलग दृष्टिकोण हैं: किसी फ़ंक्शन के भीतर होने का क्या अर्थ है?
लेक्सिकल स्कोप (या लेक्सिकल स्कोपिंग; जिसे स्टैटिक स्कोप या स्टैटिक स्कोपिंग भी कहा जाता है) में, यदि एक वैरिएबल नाम का स्कोप एक निश्चित फंक्शन है, तो इसका स्कोप फंक्शन डेफिनिशन का प्रोग्राम टेक्स्ट है: उस टेक्स्ट के भीतर, वेरिएबल नाम विद्यमान है, और है वेरिएबल के मान के लिए बाध्य है, लेकिन उस टेक्स्ट के बाहर, वेरिएबल नाम विद्यमान नहीं है। इसके विपरीत, डायनेमिक स्कोप (या डायनेमिक स्कोपिंग) में, यदि एक वेरिएबल नाम का स्कोप एक निश्चित फ़ंक्शन है, तो इसका स्कोप वह समय-अवधि है, जिसके दौरान कार्य निष्पादित हो रहा है: जब फ़ंक्शन चल रहा हो, वेरिएबल नाम विद्यमान है, और इसके मूल्य के लिए बाध्य है, लेकिन फ़ंक्शन के वापस आने के बाद, वेरिएबल नाम विद्यमान नहीं है। इसका मतलब है कि अगर फ़ंक्शन करता है f
एक अलग परिभाषित फ़ंक्शन का आह्वान करता है , फिर लेक्सिकल स्कोप के तहत, function g
की पहुँच नहीं है f
के स्थानीय वेरिएबल (g
का टेक्स्ट मानते हुए टेक्स्ट f
के अंदर नहीं है ), जबकि डायनेमिक स्कोप में, फ़ंक्शन g
की पहुंच है f
के स्थानीय वेरिएबल ( g
के आह्वान के बाद से दौरान f
का आह्वान किया जाता है ) नहीं है।
$ # bash language
$ x=1
$ function g() { echo $x ; x=2 ; }
$ function f() { local x=3 ; g ; }
$ f # does this print 1, or 3?
3
$ echo $x # does this print 1, or 2?
1
उदाहरण के लिए, दाईं ओर के प्रोग्राम पर विचार करें। पहली पंक्ति, x=1
, एक वैश्विक वेरिएबल x
बनाता है और इसे 1
से आरंभ करता है। दूसरी पंक्ति, function g() {echo $x ; एक्स = 2; }
, एक फ़ंक्शन को परिभाषित करता है g
जो वर्तमान मूल्य x
("echoes") को प्रिंट करता है, और फिर x
को 2
पर निर्धारित करता है (पिछले मान को अधिलेखित करता है)। तीसरी पंक्ति, function f() { local x=3 ; जी ; }
एक फ़ंक्शन को परिभाषित करता है f
जो एक स्थानीय वेरिएबल x
बनाता है (समान रूप से नामित वैश्विक वेरिएबल को छिपाते हुए) और इसे 3
से आरंभ करता है , और फिर g
को कॉल करता है . चौथी लाइन, f
, f
को कॉल करती है . पांचवीं पंक्ति, echo $x
, x
के वर्तमान मान को प्रिंट करती है .
तो, यह प्रोग्राम वास्तव में क्या प्रिंट करता है? यह स्कोप के नियमों पर निर्भर करता है। यदि इस प्रोग्राम की भाषा एक है जो लेक्सिकल स्कोप का उपयोग करती है, तो g
वैश्विक वेरिएबल x
को प्रिंट और संशोधित करता है (क्योंकि g
बाहर परिभाषित किया गया है ), इसलिए प्रोग्राम 1
और फिर2
प्रिंट करता है . इसके विपरीत, यदि यह भाषा डायनेमिक स्कोप का उपयोग करती है, तब g
प्रिंट और f
के स्थानीय वेरिएबल x
को संशोधित करता है (क्योंकि g
को f
के भीतर से कॉल किया जाता है ), इसलिए प्रोग्राम 3
और फिर 1
प्रिंट करता है (जैसा कि होता है, प्रोग्राम की भाषा बैश है, जो डायनेमिक स्कोप का उपयोग करती है; इसलिए प्रोग्राम 3
और फिर1
प्रिंट करता है . यदि एक ही कोड ksh93 के साथ चलाया जाता है जो लेक्सिकल स्कोप का उपयोग करता है, तो परिणाम अलग होंगे।)
लेक्सिकल स्कोप
लेक्सिकल स्कोप के साथ, एक नाम हमेशा इसके लेक्सिकल संदर्भ को संदर्भित करता है। यह प्रोग्राम टेक्स्ट की एक संपत्ति है और इसे भाषा कार्यान्वयन द्वारा रनटाइम कॉल स्टैक से स्वतंत्र बनाया गया है। क्योंकि इस मिलान के लिए केवल स्टैटिक प्रोग्राम टेक्स्ट के विश्लेषण की आवश्यकता होती है, इस प्रकार के स्कोप को स्टैटिक स्कोप भी कहा जाता है। लेक्सिकल स्कोप सभी एल्गोल- आधारित भाषाओं जैसे पास्कल, मोडुला -2 और एडा के साथ-साथ एमएल और हास्केल जैसी आधुनिक कार्यात्मक भाषाओं में मानक है। इसका उपयोग विभिन्न प्रकार की सीमाओं के साथ C और इसके वाक्य-विन्यास और सिमेंटिक रिलेटिव्स में भी किया जाता है। स्टैटिक स्कोप प्रोग्रामर को साधारण नाम प्रतिस्थापन के रूप में पैरामीटर, वेरिएबल, स्थिरांक, प्रकार, फ़ंक्शन आदि जैसे ऑब्जेक्ट संदर्भों के बारे में तर्क करने की अनुमति देता है। इससे वैकल्पिक् कोड बनाना और इसके बारे में तर्क करना बहुत आसान हो जाता है, क्योंकि स्थानीय नामकरण संरचना को अलगाव में समझा जा सकता है। इसके विपरीत, डायनेमिक स्कोप प्रोग्रामर को सभी संभावित निष्पादन संदर्भों का अनुमान लगाने के लिए मजबूर करता है जिसमें इकाई का कोड लागू किया जा सकता है।
program A;
var I:integer; K:char; procedure B; var K:real; L:integer; procedure C; var M:real; begin (*scope A+B+C*) end; (*scope A+B*) end; (*scope A*) end.
उदाहरण के लिए, पास्कल लेक्सिकली स्कॉप्ड है। पास्कल प्रोग्राम खंड को दाईं ओर देखें। वेरिएबल I
सभी बिंदुओं पर दिखाई देता है, क्योंकि यह उसी नाम के किसी अन्य वेरिएबल से कभी नहीं छिपा होता है। char
वेरिएबल K
केवल मुख्य प्रोग्राम में दिखाई देता है क्योंकि यह केवल प्रक्रिया B और C में दिखाई देने वाले real
वेरिएबल K
द्वारा छिपा हुआ है। वेरिएबल L
प्रक्रिया में भी दिखाई देता है B
और C
लेकिन यह किसी अन्य वेरिएबल को नहीं छिपाता है। वेरिएबल M
प्रक्रिया में ही दिखाई देता है C
और इसलिए प्रक्रिया B
या मुख्य प्रोग्राम से भी पहुंच योग्य नहीं है । साथ ही, प्रक्रिया प्रक्रिया C
प्रक्रिया B
में ही दिखाई देता है और इसलिए मुख्य प्रोग्राम से नहीं बुलाया जा सकता है।
प्रक्रिया B
के बाहर प्रोग्राम में डिक्लेअर एक और प्रक्रिया C
हो सकती थी। प्रोग्राम में वह स्थान जहांC
उल्लेख किया गया है तो यह निर्धारित करता है कि नामित दो प्रक्रियाओं में से कौन सी C
यह प्रतिनिधित्व करता है, इस प्रकार वेरिएबल्स के स्कोप के साथ सटीक रूप से अनुरूप है।
प्रथम श्रेणी के फ़ंक्शन के साथ भाषाओं में लेक्सिकल स्कोप का सही कार्यान्वयन नगण्य नहीं हैं, क्योंकि इसके लिए प्रत्येक फ़ंक्शन मान को अपने साथ ले जाने के लिए वेरिएबल के मानों का विवरण रखना पड़ता है, जिस पर यह निर्भर करता है (फ़ंक्शन की जोड़ी और इस संदर्भ को क्लोजर कहा जाता है)। कार्यान्वयन और कंप्यूटर वास्तुकला के आधार पर, वेरिएबल लूकप थोड़ा अक्षम हो सकता है[citation needed] जब बहुत गहराई से शाब्दिक रूप से लेक्सिकली नेस्टेड फ़ंक्शंस का उपयोग किया जाता है, हालांकि इसे कम करने के लिए प्रसिद्ध तकनीकें हैं।[8][9] साथ ही, नेस्टेड फ़ंक्शंस के लिए जो केवल अपने स्वयं के तर्कों और (तत्काल) स्थानीय वेरिएबलों को संदर्भित करते हैं, सभी सापेक्ष स्थानों को संकलन समय पर जाना जा सकता है। इस प्रकार के नेस्टेड फ़ंक्शन का उपयोग करते समय कोई ओवरहेड नहीं होता है। यह प्रोग्राम के विशेष भागों पर लागू होता है जहां नेस्टेड फ़ंक्शंस का उपयोग नहीं किया जाता है, और स्वाभाविक रूप से, ऐसी भाषा में लिखे प्रोग्रामों के लिए जहां नेस्टेड फ़ंक्शंस उपलब्ध नहीं हैं (जैसे सी भाषा में)।
इतिहास
लेक्सिकल स्कोप का पहली बार 1960 के दशक में अनिवार्य भाषा एल्गोल 60 के लिए उपयोग किया गया था और तब से अधिकांश अन्य अनिवार्य भाषाओं में इसे चुना गया है।[4]
पास्कल और सी जैसी भाषाओं में हमेशा लेक्सिकल स्कोप होता है, क्योंकि वे दोनों उन विचारों से प्रभावित होते हैं जो एल्गोल 60 और एल्गोल 68 में गए थे (हालाँकि C में लेक्सिकल नेस्टेड फ़ंक्शंस निहित नहीं थे)।
पर्ल डायनेमिक स्कोप वाली एक भाषा है जिसने बाद में स्टैटिक स्कोप जोड़ा।
मूल लिस्प अनुवादक(1960) ने डायनेमिक स्कोप का प्रयोग किया। डीप बाइंडिंग, जो स्टैटिक(लेक्सिकल) स्कोप का अनुमान लगाती है, को 1962 के आसपास लिस्प 1.5 में पेश किया गया था (जॉन मैक्कार्थी के तहत काम कर रहे स्टीव रसेल द्वारा विकसित फनार्ग उपकरण के माध्यम से)।
सभी प्रारंभिक लिस्प दुभाषियों पर आधारित होने पर डायनेमिक स्कोप का उपयोग करते थे। 1982 में, गाइ एल. स्टील जूनियर और कॉमन लिस्प ग्रुप ने कॉमन लिस्प का अवलोकन प्रकाशित किया,[10] इतिहास की एक संक्षिप्त समीक्षा और उस क्षण तक लिस्प के अलग-अलग कार्यान्वयन और उन विशेषताओं की समीक्षा जो एक सामान्य लिस्प कार्यान्वयन में होनी चाहिए। पेज 102 पर, हम पढ़ते हैं:
अधिकांश लिस्प कार्यान्वयन आंतरिक रूप से असंगत होते हैं जिसमें पूर्व निर्धारित रूप से अनुवादक और कम्पाइलर प्रोग्राम को सही करने के लिए अलग-अलग शब्दार्थ निर्दिष्ट कर सकते हैं; यह मुख्य रूप से इस तथ्य से उपजा है कि अनुवादक सभी वेरिएबलों को डायनेमिक रूप से स्कोप में रखता है, जबकि कम्पाइलर सभी वेरिएबलों को स्थानीय मानता है जब तक कि अन्यथा मानने के लिए मजबूर न किया जाए। यह सुविधा और दक्षता के लिए किया गया है, लेकिन इससे बहुत सूक्ष्म त्रुटि हो सकते हैं। सामान्य लिस्प की परिभाषा स्पष्ट रूप से अनुवादक और कम्पाइलर को सही प्रोग्रामों पर समान शब्दार्थ लगाने की आवश्यकता के द्वारा ऐसी विसंगतियों से बचाती है।
इस प्रकार सामान्य लिस्प के कार्यान्वयन के लिए सामान्य लिस्प लेक्सिकल स्कोप होना आवश्यक था। दोबारा, सामान्य लिस्प के एक सिंहावलोकन से:
इसके अलावा, सामान्य लिस्प निम्नलिखित सुविधाएं प्रदान करता है (जिनमें से अधिकांश MacLisp, InterLisp या Lisp Machines Lisp से उधार ली गई हैं): (...) पूरी तरह से लेक्सिकली स्कोप्ड वेरिएबल्स। तथाकथित FUNARG समस्या[11][12] नीचे और ऊपर दोनों स्थितियों में पूरी तरह से हल हो गया है।
उसी वर्ष जिसमें सामान्य लिस्प का एक अवलोकन(1982) प्रकाशित हुआ था, एक संकलित, शाब्दिक स्कोप वाले लिस्प, जिसे योजना प्रोग्रामिंग भाषा का इतिहास कहा जाता है, के प्रारंभिक प्रारुप(गाइ एल स्टील जूनियर द्वारा भी) प्रकाशित किए गए थे और कम्पाइलर कार्यान्वयन प्रयास किए जा रहे थे। उस समय, लिस्प में लेक्सिकल स्कोप को प्रायः लागू करने में अक्षम होने की आशंका थी। टी के इतिहास में,[13] ओलिन शिवर्स लिखते हैं:
उस समय उत्पादन में उपयोग किए जाने वाले सभी गंभीर लिस्प्स डायनेमिक रूप से स्कॉप्ड किया गया था। रैबिट[14][14] शोध(1978 में गाय लेविस स्टील जूनियर द्वारा लिखित) को ध्यान से नहीं पढ़ने वाले किसी भी व्यक्ति का मानना था कि लेक्सिकल स्कोप उड़ जाएगा;यहां तक कि जिन कुछ लोगों ने इसे पढ़ा था, वे भी विश्वास की एक छलांग ले रहे थे कि यह गंभीर उत्पादन उपयोग में काम करने वाला था।
"लेक्सिकल स्कोप" शब्द कम से कम 1967 तक है,[15] जबकि "लेक्सिकल स्कोपिंग" शब्द कम से कम 1970 तक है, जहां इसका उपयोग लिस्प बोली एमडीएल (तब "मडल" के रूप में जाना जाता है) के स्कोप के नियमों का वर्णन करने के लिए प्रोजेक्ट मैक में किया गया था।[16]
डायनेमिक स्कोप
डायनेमिक स्कोप के साथ, एक नाम निष्पादन संदर्भ को संदर्भित करता है। तकनीकी शब्दों में, इसका अर्थ है कि प्रत्येक नाम में बाइंडिंग का वैश्विक ढेर (डेटा संरचना) है। x
नाम के साथ एक स्थानीय वेरिएबल का परिचय वैश्विक x
स्टैक पर एक बाइंडिंग को धकेलता है (जो खाली हो सकता है), जो नियंत्रण प्रवाह के स्कोप को छोड़ने पर बंद हो जाता है। किसी भी संदर्भ में x
का मूल्यांकन हमेशा शीर्ष बाइंडिंग उत्पन्न होता है। ध्यान दें कि यह संकलन-समय पर नहीं किया जा सकता है क्योंकि बाइंडिंग स्टैक केवल रन टाइम (प्रोग्राम जीवनचक्र वेरिएबल) पर विद्यमान होता है, यही कारण है कि इस प्रकार के स्कोप को डायनेमिक स्कोप कहा जाता है।
आधुनिक भाषाओं में डायनेमिक स्कोप असामान्य है।[4]
प्रायः, कुछ ब्लॉक को बाइंडिंग बनाने के लिए परिभाषित किया जाता है जिसका जीवनकाल ब्लॉक का निष्पादन समय होता है; यह डायनेमिक स्कोप प्रक्रिया में स्टैटिक स्कोप की कुछ विशेषताओं को जोड़ता है। हालाँकि, चूंकि कोड के एक भाग को कई अलग-अलग स्थानों और स्थितियों से बुलाया जा सकता है, इसलिए आरंभ में यह निर्धारित करना मुश्किल हो सकता है कि जब एक वेरिएबल का उपयोग किया जाता है (या यदि कोई विद्यमान है) तो कौन सी बाइंडिंग लागू होगी। यह फायदेमंद हो सकता है; कम से कम ज्ञान के सिद्धांत के अनुप्रयोग से पता चलता है कि कोड किसी वेरिएबल के मान के कारणों (या परिस्थितियों) के आधार पर टालता है, लेकिन केवल वेरिएबल की परिभाषा के अनुसार मूल्य का उपयोग करता है। साझा किए गए डेटा की यह संकीर्ण व्याख्या किसी फ़ंक्शन के व्यवहार को सिस्टम की वर्तमान स्थिति(या नीति) के अनुकूल बनाने के लिए एक बहुत ही लचीली प्रणाली प्रदान कर सकती है। हालांकि, यह लाभ इस तरह से उपयोग किए जाने वाले सभी वेरिएबलों के सावधानीपूर्वक दस्तावेज़ीकरण के साथ-साथ एक वेरिएबल के व्यवहार के बारे में धारणाओं से बचने पर निर्भर करता है, और किसी प्रोग्राम के विभिन्न भागों के बीच हस्तक्षेप का पता लगाने के लिए कोई तंत्र प्रदान नहीं करता है। कुछ भाषाएँ, जैसे पर्ल और सामान्य लिस्प, प्रोग्रामर को एक वेरिएबल को परिभाषित या पुनर्परिभाषित करते समय स्थिर या डायनेमिक स्कोप चुनने की अनुमति देती हैं। डायनेमिक स्कोप का उपयोग करने वाली भाषाओं के उदाहरणों में लोगो (प्रोग्रामिंग भाषा), Emacs Lisp, LaTeX और शेल भाषाएँ Bash, डेबियन अल्मक्विस्ट शेल और Windows PowerShell निहित हैं।
डायनेमिक स्कोप को लागू करना काफी आसान है। किसी नाम का मान खोजने के लिए, प्रोग्राम रनटाइम स्टैक को पार कर सकता है, नाम के मान के लिए प्रत्येक सक्रियण रिकॉर्ड (प्रत्येक फ़ंक्शन का स्टैक फ़्रेम) की जाँच कर सकता है। व्यवहार में, इसे संघ सूची के उपयोग के माध्यम से और अधिक कुशल बनाया जाता है, जो नाम/मूल्य जोड़े का ढेर है। जब भी डिक्लेरेशन की जाती है तो जोड़े को इस स्टैक पर धकेल दिया जाता है, और जब भी वेरिएबल संदर्भ से बाहर हो जाते हैं तो पॉप हो जाते हैं।[17] शालो बाइंडिंग एक वैकल्पिक रणनीति है जो काफी तेज है, एक केंद्रीय संदर्भ तालिका का उपयोग करती है, जो प्रत्येक नाम को अर्थों के ढेर के साथ जोड़ती है। यह एक विशेष नाम खोजने के लिए रन-टाइम के दौरान एक रैखिक खोज से बचा जाता है, लेकिन इस तालिका को ठीक से बनाए रखने के लिए सावधानी बरतनी चाहिए।[17] ध्यान दें कि ये दोनों रणनीतियाँ किसी एक वेरिएबल के लिए बाइंडिंग के लिए अंतिम-इन-फर्स्ट-आउट (एलआईएफओ) का आदेश मानती हैं; व्यवहार में सभी बन्धन इसी क्रम में होते हैं।
सरल वैश्विक वेरिएबल के साथ डायनेमिक वेरिएबल का प्रतिनिधित्व एक और भी सरल कार्यान्वयन है। प्रोग्राम के लिए अदृश्य स्टैक पर अज्ञात स्थान में मूल मान को सहेजकर स्थानीय बाध्यकारी किया जाता है। जब वह बाध्यकारी स्कोप समाप्त हो जाता है, तो मूल मान इस स्थान से पुनर्स्थापित किया जाता है। वास्तव में, डायनेमिक स्कोप की उत्पत्ति इसी तरीके से हुई। लिस्प के आरंभी कार्यान्वयन ने स्थानीय वेरिएबलों को लागू करने के लिए इस स्पष्ट रणनीति का प्रयोग किया, और यह अभ्यास कुछ बोलियों में जीवित है जो अभी भी उपयोग में हैं, जैसे कि GNU Emacs Lisp। लिस्प में बाद में लेक्सिकल स्कोप पेश किया गया था। यह उपरोक्त शैलो बाइंडिंग योजना के बराबर है, सिवाय इसके कि केंद्रीय संदर्भ तालिका केवल वैश्विक वेरिएबल बाध्यकारी संदर्भ है, जिसमें वेरिएबल का वर्तमान अर्थ इसका वैश्विक मूल्य है। वैश्विक वेरिएबल बनाए रखना जटिल नहीं है। उदाहरण के लिए, एक प्रतीक ऑब्जेक्ट के वैश्विक मूल्य के लिए एक समर्पित खाँचा हो सकता है।
डायनेमिक स्कोप थ्रेड-लोकल स्टोरेज के लिए एक उत्कृष्ट अमूर्तता प्रदान करता है, लेकिन अगर इसका उपयोग इस तरह किया जाता है तो यह वैश्विक वेरिएबल को बचाने और पुनर्स्थापित करने पर आधारित नहीं हो सकता है। प्रत्येक वेरिएबल के लिए थ्रेड-स्थानीय कुंजी रखने के लिए एक संभावित कार्यान्वयन रणनीति है। जब वेरिएबल का उपयोग किया जाता है, तो थ्रेड-स्थानीय कुंजी का उपयोग थ्रेड-लोकल मेमोरी लोकेशन तक पहुंचने के लिए किया जाता है (कम्पाइलर द्वारा उत्पन्न कोड द्वारा, जो जानता है कि कौन से वेरिएबल डायनेमिक हैं और कौन से लेक्सिकल हैं)। यदि कॉलिंग थ्रेड के लिए थ्रेड-लोकल कुंजी विद्यमान नहीं है, तो वैश्विक स्थान का उपयोग किया जाता है। जब एक वेरिएबल स्थानीय रूप से बाध्य होता है, तो पूर्व मान स्टैक पर छिपे हुए स्थान में संग्रहीत होता है। थ्रेड-लोकल स्टोरेज को वेरिएबल की के तहत बनाया जाता है, और नया मान वहां संग्रह किया जाता है। उस थ्रेड के भीतर वेरिएबल के नेस्टेड ओवरराइड बस इस थ्रेड-लोकल लोकेशन को जमा और सुधार करते हैं। जब प्रारंभिक, सबसे बाहरी ओवरराइड का संदर्भ समाप्त हो जाता है, तो थ्रेड-स्थानीय कुंजी को हटा दिया जाता है, वेरिएबल के वैश्विक संस्करण को एक बार फिर उस थ्रेड पर उजागर किया जाता है।
संदर्भात्मक पारदर्शिता के साथ डायनामिक स्कोप केवल वर्तमान फ़ंक्शन के तर्क स्टैक तक ही सीमित है, और लेक्सिकल स्कोप के साथ मेल खाता है।
मैक्रो विस्तार
आधुनिक भाषाओं में, प्रीप्रोसेसर में मैक्रो विस्तार वास्तविक डायनेमिक स्कोप का एक प्रमुख उदाहरण है। मैक्रो भाषा ही नामों को हल किए बिना केवल स्रोत कोड को रूपांतरित करती है, लेकिन चूंकि विस्तार किया जाता है, जब विस्तारित टेक्स्ट में नाम तब हल किए जाते हैं (विशेष रूप से मुक्त वेरिएबल), वे जहां वे विस्तारित होते हैं, उसके आधार पर हल किए जाते हैं (शिथिल रूप से "कहा जाता है"), जैसे डायनेमिक स्कोप हो रहा था।
मैक्रो विस्तार के लिए उपयोग किए जाने वाले सी प्रीप्रोसेसर में वास्तविक डायनेमिक स्कोप है, क्योंकि यह स्वयं नाम संकल्प नहीं करता है और यह स्वतंत्र है कि मैक्रो परिभाषित किया गया है। उदाहरण के लिए, मैक्रो:
#define ADD_A(x) x + a
स्वीकृत किए गए वेरिएबल में a
जोड़ने के लिए विस्तारित होगा, इस नाम के साथ ही बाद में कंपाइलर द्वारा हल किया गया जहां मैक्रो ADD_A को "कहा जाता है" (ठीक से, विस्तारित)।उचित रूप से, सी प्रीप्रोसेसर केवल लेक्सिकल विश्लेषण करता है, टोकेनाइजेशन चरण के दौरान मैक्रो का विस्तार करता है, लेकिन सिंटैक्स ट्री में पार्सिंग या नाम रिज़ॉल्यूशन नहीं करता है।
उदाहरण के लिए, निम्नलिखित कोड में, नामa
मैक्रो में विस्तार स्थल पर स्थानीय वेरिएबल के लिए (विस्तार के बाद) हल किया गया है:
#define ADD_A(x) x + a
void add_one(int *x) { const int a = 1; *x = ADD_A(*x); } void add_two(int *x) { const int a = 2; *x = ADD_A(*x); }
योग्य नाम
जैसा कि हमने देखा है, स्कोप के प्रमुख कारणों में से एक यह है कि यह नाम के टकराव को रोकने में मदद करता है, समान नामों को अलग-अलग चीजों को संदर्भित करने की अनुमति देकर, इस प्रतिबंध के साथ कि नामों के अलग-अलग स्कोप होने चाहिए। कभी-कभी यह प्रतिबंध असुविधाजनक होता है; जब एक प्रोग्राम में कई अलग-अलग चीजों को अभिगम करने की आवश्यकता होती है, तो प्रायः सभी को वैश्विक स्कोप वाले नामों की आवश्यकता होती है, इसलिए नाम टकराव से बचने के लिए विभिन्न तकनीकों की आवश्यकता होती है।
इसे संबोधित करने के लिए, कई भाषाएँ वैश्विक नामों को व्यवस्थित करने के लिए तंत्र प्रदान करती हैं। इन तंत्रों का विवरण, और उपयोग की जाने वाली शर्तें, भाषा पर निर्भर करती हैं; लेकिन सामान्य विचार यह है कि नामों के एक समूह को स्वयं एक नाम दिया जा सकता है - एक उपसर्ग - और, जब आवश्यक हो, एक इकाई को एक योग्य नाम से संदर्भित किया जा सकता है जिसमें नाम और उपसर्ग निहित हैं। प्रायः इस तरह के नामों में दो प्रकार के स्कोप होंगे: एक स्कोप(प्रायः वैश्विक स्कोप) जिसमें योग्य नाम दिखाई देता है, और एक या एक से अधिक संकीर्ण क्षेत्र जिसमें अयोग्य नाम (उपसर्ग के बिना) दिखाई देता कुंआ है। और प्रायः इन समूहों को स्वयं समूहों में संगठित किया जा सकता है; यानी उन्हें नेस्टेड किया जा सकता है।
हालाँकि कई भाषाएँ इस अवधारणा का समर्थन करती हैं, विवरण बहुत भिन्न होते हैं। कुछ भाषाओं में तंत्र होते हैं, जैसे सी ++ और सी शार्प| सी # में नामस्थान, जो वैश्विक नामों को समूहों में व्यवस्थित करने के लिए लगभग विशेष रूप से सेवा प्रदान करते हैं। अन्य भाषाओं में प्रक्रिया हैं, जैसे एडा में पैकेज और मानक एमएल में संरचनाएं, जो कुछ नामों को केवल उनके समूह के अन्य सदस्यों को दिखाई देने की अनुमति देने के अतिरिक्त उद्देश्य से जोड़ती हैं। और वस्तु-उन्मुख भाषाएँ प्रायः इस उद्देश्य को पूरा करने के लिए क्लासेज या सिंगलटन ऑब्जेक्ट्स की अनुमति देती हैं (चाहे उनके पास एक प्रक्रिया भी हो जिसके लिए यह प्राथमिक उद्देश्य है)। इसके अलावा, भाषाएं प्रायः इन दृष्टिकोणों को जोड़ती हैं; उदाहरण के लिए, पर्ल के पैकेज मोटे तौर पर C++ के नामस्थान के समान हैं, लेकिन ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग के लिए क्लासेज के रूप में वैकल्पिक रूप से दोगुने हैं; और जावा अपने वेरिएबल और फंक्शन्स को क्लासेज में व्यवस्थित करता है, लेकिन फिर उन क्लासेज को एडा-जैसे पैकेजों में व्यवस्थित करता है।
भाषा द्वारा
This section needs expansion. You can help by adding to it. (अप्रैल 2013) |
प्रतिनिधि भाषाओं के लिए स्कोप के नियम पालन करते हैं।
सी
C में, स्कोप को परंपरागत रूप से विशेष रूप से वेरिएबल्स के लिए लिंकेज (सॉफ्टवेयर) या दृश्यता के रूप में जाना जाता है। सी वैश्विक स्कोप (बाहरी लिंकेज के रूप में जाना जाता है), इकाई स्कोप या फ़ाइल स्कोप का एक रूप (आंतरिक लिंकेज के रूप में जाना जाता है), और स्थानीय स्कोप एक फंक्शन के भीतर) के साथ एक शाब्दिक स्कोप वाली भाषा है; एक फ़ंक्शन स्कोप के भीतर आगे ब्लॉक स्कोप के माध्यम से नेस्ट किया जा सकता है। हालाँकि, मानक C नेस्टेड फ़ंक्शंस का समर्थन नहीं करता है।
एक वेरिएबल का जीवनकाल और दृश्यता उसके स्टोरेज क्लास द्वारा निर्धारित की जाती है। सी में तीन प्रकार के जीवन काल हैं: स्थैतिक (प्रोग्राम निष्पादन), स्वचालित (ब्लॉक निष्पादन, ढेर पर आवंटित), और मैनुअल (ढेर पर आवंटित)। वेरिएबल के लिए केवल स्थिर और स्वचालित समर्थित हैं और कम्पाइलर द्वारा नियंत्रित किया जाता है, जबकि मैन्युअल रूप से आवंटित मेमोरी को विभिन्न वेरिएबलों में मैन्युअल रूप से पता लगाना चाहिए। C में दृश्यता के तीन स्तर हैं: बाहरी लिंकेज (वैश्विक), आंतरिक लिंकेज (रफ्ली फ़ाइल), और ब्लॉक स्कोप (जिसमें फ़ंक्शन निहित हैं); ब्लॉक स्कोप को नेस्टेड किया जा सकता है, और निहित के उपयोग से आंतरिक लिंकेज के विभिन्न स्तरों को संभव है। सी में आंतरिक लिंकेज अनुवाद इकाई (प्रोग्रामिंग) स्तर पर दृश्यता है, अर्थात् सी प्रीप्रोसेसर द्वारा संसाधित किए जाने के बाद एक स्रोत फ़ाइल, विशेष रूप से सभी प्रासंगिक निहित हैं।
C प्रोग्राम को अलग-अलग ऑब्जेक्ट फ़ाइल के रूप में संकलित किया जाता है, जो तब एक निष्पादन योग्य या लाइब्रेरी में एक लिंकर के माध्यम से जुड़े होते हैं। इस प्रकार नाम रेजोलुशन कम्पाइलर में विभाजित होता है, जो अनुवाद इकाई के भीतर नामों को हल करता है (अधिक शिथिल, संकलन इकाई, लेकिन यह ठीक से एक अलग अवधारणा है), और लिंकर, जो अनुवाद इकाइयों में नामों को हल करता है; आगे की चर्चा के लिए लिंकेज (सॉफ्टवेयर) देखें।
सी में, ब्लॉक स्कोप वाले वेरिएबल संदर्भ में प्रवेश करते हैं जब उन्हें डिक्लेअर किया जाता है (ब्लॉक के शीर्ष पर नहीं), संदर्भ से बाहर जाएं यदि कोई (गैर-नेस्टेड) फ़ंक्शन ब्लॉक के भीतर कहा जाता है, फ़ंक्शन रिटर्न आने पर संदर्भ में आ जाता है, और ब्लॉक के अंत में संदर्भ से बाहर जाएं। स्वचालित स्थानीय वेरिएबल के मामले में, उन्हें डिक्लेरेशन पर भी आवंटित किया जाता है और ब्लॉक के अंत में हटा दिया जाता है, जबकि स्थिर स्थानीय वेरिएबल के लिए, उन्हें प्रोग्राम के प्रारंभ में आवंटित किया जाता है और प्रोग्राम की समाप्ति पर हटा दिया जाता है।
निम्नलिखित प्रोग्राम ब्लॉक के माध्यम से संदर्भ भाग में आने वाले ब्लॉक स्कोप के साथ एक वेरिएबल प्रदर्शित करता है, फिर ब्लॉक समाप्त होने पर संदर्भ से बाहर निकलता है (और वस्तुत: हटा दिया जाता है):
#include <stdio.h>
int main(void) { char x = 'm'; printf("%c\n", x); { printf("%c\n", x); char x = 'b'; printf("%c\n", x); } printf("%c\n", x); }
प्रोग्राम आउटपुट:
m
m
b
m
सी में स्कोप के अन्य स्तर हैं।[18] फ़ंक्शन प्रोटोटाइप में उपयोग किए जाने वाले वेरिएबल नामों में फ़ंक्शन प्रोटोटाइप दृश्यता होती है, और फ़ंक्शन प्रोटोटाइप के अंत में संदर्भ से बाहर निकलता है। चूंकि नाम का उपयोग नहीं किया गया है, यह संकलन के लिए उपयोगी नहीं है, लेकिन प्रलेखन के लिए उपयोगी हो सकता है। GOTO स्टेटमेंट के लेबल नामों में फंक्शन स्कोप होता है, जबकि स्विच स्टेटमेंट्स के केस लेबल नामों में ब्लॉक स्कोप (स्विच का ब्लॉक) होता है।
सी ++
किसी प्रोग्राम में हम जिन वेरिएबल्स का उपयोग करने का अभिप्राय रखते हैं, उन्हें पहले इसके टाइप स्पेसिफायर के साथ डिक्लेअर किया जाना चाहिए, कोड में इंगित करें, जैसा कि हमने पिछले कोड में फ़ंक्शन मेन भाग के आरंभ में किया था जब हमने डिक्लेअर किया कि a, b, और रिजल्ट int प्रकार के थे। एक वेरिएबल या तो वैश्विक या स्थानीय स्कोप का हो सकता है। एक वैश्विक वेरिएबल एक वेरिएबल है जिसे मुख्य निकाय में डिक्लेअर किया गया है स्रोत कोड, सभी फ़ंक्शन के बाहर, जबकि एक स्थानीय वेरिएबल एक फ़ंक्शन या ब्लॉक के ढांचे के भीतर डिक्लेअर किया जाता है।
आधुनिक संस्करण नेस्टेड लेक्सिकल स्कोप को अनुमति देता है।
स्विफ्ट
स्विफ्ट (प्रोग्रामिंग भाषा) में C ++ के साथ स्कोप के लिए एक समान नियम है, लेकिन इसमें अलग-अलग एक्सेस मॉडिफायर्स निहित हैं।
Modifier | Immediate scope | File | Containing module/package | Rest of the world |
---|---|---|---|---|
open | Yes | Yes | Yes | Yes, allows subclass |
public | Yes | Yes | Yes | Yes, disallows subclass |
internal | Yes | Yes | Yes | No |
fileprivate | Yes | Yes | No | No |
private | Yes | No | No | No |
गो
गो (प्रोग्रामिंग लैंग्वेज) ब्लॉक का उपयोग करके लेक्सिक रूप से स्कॉप्ड है।[3]
जावा
जावा (प्रोग्रामिंग लैंग्वेज) लेक्सिकली स्कोप्ड है।
जावा वर्ग में तीन प्रकार के वेरिएबल हो सकते हैं:[19]
- स्थानीय वेरिएबल
- एक विधि या एक विशेष ब्लॉक के अंदर परिभाषित होते हैं। ये वेरिएबल स्थानीय हैं जहां उन्हें निचले स्तर पर परिभाषित किया गया था। और उदाहरण के लिए, एक विधि के अंदर एक लूप उस विधि के स्थानीय वेरिएबल का उपयोग कर सकता है, लेकिन दूसरी तरफ नहीं। लूप के वेरिएबल (उस लूप के लिए स्थानीय) लूप समाप्त होते ही नष्ट हो जाते हैं।
- सदस्य वेरिएबल
- जिसे फ़ील्ड भी कहा जाता है, किसी भी विधि के बाहर क्लास के भीतर डिक्लेअर वेरिएबल होते हैं। पूर्व निर्धारित रूप से, ये वेरिएबल उस क्लास के भीतर और पैकेज में सभी क्लासेज के लिए भी उपलब्ध हैं।
- पैरामीटर्स
- विधि डिक्लेरेशन में वेरिएबल हैं।
प्रायः, कोष्ठक का एक समूह एक विशेष स्कोप को परिभाषित करता है, लेकिन क्लास के भीतर शीर्ष स्तर पर वेरिएबल्स उनके व्यवहार में भिन्न हो सकते हैं जो उनकी परिभाषा में उपयोग किए जाने वाले संशोधक कीवर्ड के आधार पर भिन्न हो सकते हैं। निम्न तालिका प्रत्येक संशोधक द्वारा अनुमत सदस्यों तक पहुंच दिखाती है।[20]
Modifier | Class | Package | Subclass | World |
---|---|---|---|---|
public | Yes | Yes | Yes | Yes |
protected | Yes | Yes | Yes | No |
(no modifier) | Yes | Yes | No | No |
private | Yes | No | No | No |
जावास्क्रिप्ट
जावास्क्रिप्ट में सरल स्कोप के नियम हैं,[21] लेकिन वेरिएबल इनिशियलाइज़ेशन और नाम रिज़ॉल्यूशन नियम समस्याएँ पैदा कर सकते हैं, और कॉलबैक के लिए क्लोजर के व्यापक उपयोग का अर्थ है परिभाषित होने पर फ़ंक्शन का लेक्सिकल संदर्भ (जो नाम रिज़ॉल्यूशन के लिए उपयोग किया जाता है) लेक्सिकल संदर्भ से बहुत अलग हो सकता है जब इसे कहा जाता है(जो नाम समाधान के लिए अप्रासंगिक है)। जावास्क्रिप्ट ऑब्जेक्ट्स में गुणों के लिए नाम समाधान होता है, लेकिन यह एक अलग विषय है।
जावास्क्रिप्ट में लेक्सिकल स्कोप है [22] फंक्शन स्तर पर नेस्टेड, वैश्विक संदर्भ सबसे बाहरी संदर्भ होने के साथ है। इस स्कोप का उपयोग वेरिएबल और फंक्शन दोनों के लिए किया जाता है (अर्थात् फ़ंक्शन डिक्लेरेशन, फ़ंक्शन प्रकार के वेरिएबल के विपरीत)।[23] ECMAScript 6 के बाद सेlet
और const
कीवर्ड के साथ ब्लॉक स्कोप मानक है। पूरे ब्लॉक को एक फंक्शन में लपेटकर और फिर इसे निष्पादित करके ब्लॉक स्कोप का उत्पादन किया जा सकता है; इसे तत्काल-आमंत्रित फ़ंक्शन एक्सप्रेशन (IIFE) प्रतिरूप के रूप में जाना जाता है।
जबकि जावास्क्रिप्ट का स्कोप सरल है - लेक्सिकल, फंक्शन-लेवल - संबद्ध इनिशियलाइज़ेशन और नाम रिज़ॉल्यूशन नियम भ्रम का कारण हैं। सबसे पहले, एक नाम के लिए असाइनमेंट एक नया वैश्विक वेरिएबल बनाने के लिए पूर्व निर्धारित नहीं है, और स्थानीय भी नहीं है। दूसरे, एक नया स्थानीय वेरिएबल बनाने के लिए एक का उपयोग करना चाहिए var
कीवर्ड; वेरिएबल तब मान के साथ फ़ंक्शन के शीर्ष पर बनाया जाता है undefined
और जब असाइनमेंट एक्सप्रेशन तक पहुँच जाता है तो वेरिएबल को उसका मान दिया जाता है:
- वेरिएबलस्टेटमेंट निष्पादित होने पर एक प्रारंभकर्ता के साथ एक वेरिएबल को उसके असाइनमेंटएक्सप्रेशन का मान निर्दिष्ट किया जाता है, न कि जब वेरिएबल बनाया जाता है।[24]
इसे वेरिएबल हॉइस्टिंग के रूप में जाना जाता है[25]- डिक्लेरेशन, लेकिन इनिशियलाइज़ेशनन हीं, फ़ंक्शन के शीर्ष पर फहराया जाता है। तीसरा, इनिशियलाइज़ेशन यील्ड से पहले undefined
सिंटैक्स त्रुटि के बजाय वेरिएबल्स को एक्सेस करना। चौथा, फंक्शन डिक्लेरेशन के लिए, डिक्लेरेशन और इनिशियलाइज़ेशन दोनों को फंक्शन के शीर्ष पर वेरिएबल इनिशियलाइज़ेशन के विपरीत होइस्टिंग किया जाता है। उदाहरण के लिए, निम्न कोड आउटपुट undefined के साथ एक संवाद उत्पन्न करता है, क्योंकि स्थानीय वेरिएबल डिक्लेरेशन को होइस्टिंग किया जाता है, वैश्विक वेरिएबल को छायांकित किया जाता है, लेकिन इनिशियलाइज़ेशन नहीं होता है, इसलिए उपयोग किए जाने पर वेरिएबल अपरिभाषित होता है:
a = 1;
function f() { alert(a); var a = 2; } f();
इसके अलावा, चूंकि फ़ंक्शंस जावास्क्रिप्ट में प्रथम श्रेणी की ऑब्जेक्ट्स हैं और उन्हें प्रायः कॉलबैक के रूप में नियुक्त किया जाता है या फ़ंक्शन से रिटर्न किया जाता है, जब कोई फ़ंक्शन निष्पादित होता है, तो नाम रिज़ॉल्यूशन इस बात पर निर्भर करता है कि इसे मूल रूप से कहाँ परिभाषित किया गया था (परिभाषा का लेक्सिकल संदर्भ), न कि लेक्सिकल संदर्भ या निष्पादन संदर्भ जहां इसे कहा जाता है। जावास्क्रिप्ट में एक विशेष फ़ंक्शन (अधिकांश वैश्विक से अधिकांश स्थानीय तक) के नेस्टेड स्कोप, विशेष रूप से कॉलबैक के रूप में उपयोग किए जाने वाले क्लोजर को कभी-कभी स्कोप चेन के रूप में संदर्भित किया जाता है, जो किसी ऑब्जेक्ट की प्रोटोटाइप श्रृंखला के अनुरूप होता है।
क्लोजर जावास्क्रिप्ट में नेस्टेड फ़ंक्शंस का उपयोग करके उत्पादित किया जा सकता है, क्योंकि फ़ंक्शंस प्रथम श्रेणी की वस्तुएं हैं।[26] एक संलग्न फ़ंक्शन से एक नेस्टेड फ़ंक्शन को वापस करने में संलग्न फ़ंक्शन के स्थानीय वेरिएबल निहित होते हैं, जो कि एक बंद करने वाले फ़ंक्शन के (गैर-स्थानीय) लेक्सिकल संदर्भ के रूप में होते हैं। उदाहरण के लिए:
function newCounter() {
// return a counter that is incremented on call (starting at 0) // and which returns its new value var a = 0; var b = function() { a++; return a; }; return b; } c = newCounter(); alert(c() + ' ' + c()); // outputs "1 2"
कॉलबैक के लिए उपयोग किए जाने के कारण जावास्क्रिप्ट में क्लोजर का प्रायः उपयोग किया जाता है। दरअसल, कॉलबैक के रूप में स्थानीय संदर्भ में किसी फ़ंक्शन का कोई भी हुकिंग या फ़ंक्शन से इसे रिटर्न करने से फ़ंक्शन बॉडी में कोई भी अनबाउंड वेरिएबल होने पर बंद हो जाता है (वर्तमान लेक्सिकल संदर्भ के नेस्टेड स्कोप के आधार पर क्लोजर के संदर्भ में) , या स्कोप चेन); यह आकस्मिक हो सकता है। मापदंडों के आधार पर कॉलबैक बनाते समय, मापदंडों को एक क्लोजर में संग्रहित किया जाना चाहिए, अन्यथा यह गलती से एक क्लोजर बना देगा जो कि संलग्न संदर्भ में वेरिएबल को संदर्भित करता है, जो बदल सकता है।[27]
जावास्क्रिप्ट ऑब्जेक्ट्स के गुणों का नाम रिज़ोलुशन प्रोटोटाइप ट्री में इनहेरिटेंस पर आधारित है- पेड़ में जड़ के पथ को प्रोटोटाइप श्रृंखला कहा जाता है- और वेरिएबल और फंक्शन के नाम रिज़ोलुशन से अलग होता है।
लिस्प
लिस्प बोलियों के स्कोप के लिए विभिन्न नियम हैं।
मूल लिस्प ने डायनेमिक स्कोप का प्रयोग किया; यह एल्गोल से प्रेरित स्कीम थी, जिसने लिस्प परिवार के लिए स्थिर (लेक्सिकल) स्कोप पेश की।
Maclisp ने संकलित कोड में पूर्व निर्धारित रूप से इंटरप्रेटर और लेक्सिकल स्कोप में डायनेमिक स्कोप का उपयोग किया, हालांकि संकलित कोड SPECIAL
विशेष वेरिएबल के लिए डिक्लेरेशन के उपयोग से डायनामिक बाइंडिंग तक पहुंच सकता है ।[28] हालांकि, मैक्लिस्प ने लेक्सिकल बाइंडिंग को आधुनिक भाषाओं में अपेक्षा से अधिक एक अनुकूलन के रूप में माना, और यह क्लोजर (कंप्यूटर प्रोग्रामिंग) सुविधा के साथ नहीं आया, जो आधुनिक लिस्प्स में लेक्सिकल स्कोप की अपेक्षा कर सकता है। एक अलग ऑपरेशन, *फंक्शन
, उस मुद्दे के कुछ हद तक अनाड़ी ढंग से काम करने के लिए उपलब्ध था।[29]
कॉमन लिस्प ने स्कीम (प्रोग्रामिंग लैंग्वेज) से क्लोजर के रूप में लेक्सिकल स्कोप अपनाया,[30]।
ISLISP में साधारण वेरिएबलों के लिए लेक्सिकल स्कोप है। इसमें डायनेमिक वेरिएबल भी हैं, लेकिन वे सभी स्थितियों में स्पष्ट रूप से चिह्नित हैं; उन्हें ए defdynamic
विशेष रूप द्वारा परिभाषित किया जाना चाहिए , एक से बंधा हुआ dynamic-let
विशेष रूप, और एक स्पष्ट dynamic
विशेष फॉर्म द्वारा एक्सेस किया जाना चाहिए ।[31]
लिस्प की कुछ अन्य बोलियाँ, जैसे Emacs Lisp, अभी भी पूर्व निर्धारित रूप से डायनेमिक स्कोप का उपयोग करती हैं। Emacs Lisp में अब प्रति-बफ़र आधार पर लेक्सिकल स्कोप उपलब्ध है।[32]
पायथन
वेरिएबल्स के लिए, पायथन में फंक्शन स्कोप, इकाई स्कोप और ग्लोबल स्कोप है। स्कोप (फ़ंक्शन, इकाई, या ग्लोबल स्कोप) के आरंभ में नाम संदर्भ में प्रवेश करते हैं, और जब गैर-नेस्टेड फ़ंक्शन को कॉल किया जाता है या स्कोप समाप्त होता है, तो संदर्भ से बाहर निकल जाते हैं। यदि किसी नाम का उपयोग वेरिएबल इनिशियलाइज़ेशन से पहले किया जाता है, तो यह एक रनटाइम अपवाद उठाता है। यदि एक वेरिएबल को आसानी से एक्सेस किया जाता है (इसे असाइन नहीं किया जाता है), तो नाम रिज़ॉल्यूशन LEGB (लोकल, एनक्लोज़िंग, ग्लोबल, बिल्ट-इन) नियम का पालन करता है, जो नामों को सबसे कम प्रासंगिक संदर्भ में हल करता है। हालाँकि, यदि एक वेरिएबल को सौंपा गया है, तो यह एक वेरिएबल डिक्लेअर करने के लिए चूक करता है जिसका स्कोप स्तर (फ़ंक्शन, इकाई या वैश्विक) के आरंभ में शुरू होता है, न कि असाइनमेंट पर। इन दोनों नियमों को a से ओवरराइड किया जा सकता है global
या nonlocal
(पायथन 3 में) उपयोग से पहले डिक्लेरेशन, जो मास्किंग गैर-स्थानीय वेरिएबल होने पर भी वैश्विक वेरिएबलों तक पहुँचने की अनुमति देता है, और वैश्विक या गैर-स्थानीय वेरिएबलों को असाइन करता है।
एक साधारण उदाहरण के रूप में, एक फ़ंक्शन एक वेरिएबल को वैश्विक स्कोप में हल करता है:
>>> def f():
... print(x)
...
>>> x = "global"
>>> f()
global
ध्यान दें कि x
पहले परिभाषित किया गया है f
कहा जाता है, इसलिए कोई त्रुटि नहीं उठाई जाती है, भले ही इसे परिभाषा में इसके संदर्भ के बाद f
परिभाषित किया गया हो . लेक्सिकली यह एक आगे का संदर्भ है, जिसकी अनुमति पायथन में है।
यहाँ असाइनमेंट एक नया स्थानीय वेरिएबल बनाता है, जो वैश्विक वेरिएबल के मान को नहीं बदलता है:
>>> def f():
... x = "f"
... print(x)
...
>>> x = "global"
>>> print(x)
global
>>> f()
f
>>> print(x)
global
किसी फ़ंक्शन के भीतर एक वेरिएबल के लिए असाइनमेंट इसे फ़ंक्शन के लिए स्थानीय डिक्लेअर करने का कारण बनता है, इसलिए इसका स्कोप संपूर्ण कार्य है, और इस प्रकार इस असाइनमेंट से पहले इसका उपयोग करने से त्रुटि उत्पन्न होती है। यह सी से अलग है, जहां स्थानीय वेरिएबल का स्कोप इसकी डिक्लेरेशन पर शुरू होता है। यह कोड एक त्रुटि उठाता है:
>>> def f():
... print(x) ... x = "f" ... >>> x = "global" >>> f() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in f UnboundLocalError: local variable 'x' referenced before assignment
पूर्व निर्धारित नाम रिज़ॉल्यूशन नियमों को global
या nonlocal
(पायथन 3 में) कीवर्ड इसके साथ ओवरराइड किया जा सकता है। नीचे दिए गए कोड में, global x
में डिक्लेरेशनg
मतलब कि x
वैश्विक वेरिएबल को हल करता है। इस प्रकार इसे एक्सेस किया जा सकता है (जैसा कि इसे पहले ही परिभाषित किया जा चुका है), और असाइनमेंट एक नया स्थानीय वैरिएबल डिक्लेअर करने के बजाय ग्लोबल वैरिएबल को असाइन करता है। ध्यान दें f
में कोई global
डिक्लेरेशन की आवश्यकता नहीं है -चूंकि यह वेरिएबल को निर्दिष्ट नहीं करता है, यह वैश्विक वेरिएबल को हल करने के लिए पूर्वनिर्धारित है।
>>> def f():
... print(x)
...
>>> def g():
... global x
... print(x)
... x = "g"
... >>> x = "global"
>>> f()
global
>>> g()
global
>>> f()
g
global
नेस्टेड फंक्शन के लिए भी प्रयोग किया जा सकता है। एक गैर-स्थानीय वेरिएबल की उपस्थिति में एक वैश्विक वेरिएबल के लिए असाइनमेंट की अनुमति देने के अलावा, इसका उपयोग वैश्विक वेरिएबल तक पहुंचने के लिए भी किया जा सकता है:
>>> def f():
... def g():
... global x
... print(x)
... x = "f"
... g()
...
>>> x = "global"
>>> f()
global
स्टेड फ़ंक्शंस के लिए, गैर-लोकल वैरिएबल को असाइन करने के लिए नॉनलोकल डिक्लेरेशन भी होता है, जो एक अननेस्टेड फ़ंक्शन में ग्लोबल का उपयोग करने के समान होता है:
>>> def f():
... def g():
... nonlocal x # Python 3 only
... x = "g"
... x = "f"
... g()
... print(x)
...
>>> x = "global"
>>> f()
g
>>> print(x)
global
आर
S (प्रोग्रामिंग लैंग्वेज) के अन्य कार्यान्वयनों के विपरीत, R एक लेक्सिकली स्कोप्ड लैंग्वेज है, जहां मुक्त वेरिएबल के मान वैश्विक वेरिएबल के एक समूह द्वारा निर्धारित किए जाते हैं, जबकि R में वे उस संदर्भ द्वारा निर्धारित किए जाते हैं जिसमें फ़ंक्शन बनाया गया था। .[33] स्कोप के संदर्भों को विभिन्न प्रकार की विशेषताओं (जैसे parent.frame()
) जो प्रोग्रामर की इच्छा के अनुसार डायनेमिक स्कोप के अनुभव का अनुकरण कर सकता है।
कोई ब्लॉक स्कोप नहीं है:
a <- 1
{ a <- 2 } message(a) ## 2
फंक्शन के पास उस स्कोप तक पहुंच है जिसमें वे बनाए गए थे:
a <- 1
f <- function() { message(a) } f() ## 1
किसी फ़ंक्शन के भीतर बनाए गए या संशोधित वेरिएबल वहां रहते हैं:
a <- 1
f <- function() { message(a) a <- 2 message(a) } f() ## 1 ## 2 message(a) ## 1
किसी फ़ंक्शन के भीतर बनाए या संशोधित किए गए वेरिएबल तब तक बने रहते हैं जब तक कि स्कोप को संलग्न करने के लिए स्पष्ट रूप से अनुरोध नहीं किया जाता है:
a <- 1
f <- function() { message(a) a <<- 2 message(a) } f() ## 1 ## 2 message(a) ## 2
हालाँकि R में पूर्व निर्धारित रूप से लेक्सिकल स्कोप है, फंक्शन स्कोप्स को बदला जा सकता है:
a <- 1
f <- function() { message(a) } my_env <- new.env() my_env$a <- 2 f() ## 1 environment(f) <- my_env f() ## 2
यह भी देखें
- क्लोजर (कंप्यूटर साइंस)
- वैश्विक वेरिएबल
- स्थानीय वेरिएबल
- चलो एक्सप्रेशन
- गैर-स्थानीय वेरिएबल
- नेम बाइंडिंग
- नाम संकल्प (प्रोग्रामिंग भाषाओं)
- वेरिएबल (प्रोग्रामिंग) # स्कोप और सीमा | वेरिएबल्स (स्कोप और सीमा)
- जानकारी छुपाना
- जावास्क्रिप्ट में तत्काल-आमंत्रित फ़ंक्शन एक्सप्रेशन
- ऑब्जेक्ट लाइफटाइम
टिप्पणियाँ
- ↑ See definition for meaning of "scope" versus "context".
- ↑ "Dynamic scope" bases name resolution on extent (lifetime), not scope, and thus is formally inaccurate.
- ↑ For example, the Jinja template engine for Python by default uses both lexical scope (for imports) and dynamic scope (for includes), and allows behavior to be specified with keywords; see Import Context Behavior.
- ↑ "Name resolution" and "name binding" are largely synonymous; narrowly speaking "resolution" determines to which name a particular use of a name refers, without associating it with any meaning, as in higher-order abstract syntax, while "binding" associates the name with an actual meaning. In practice the terms are used interchangeably.
- ↑ For self-modifying code the lexical context itself can change during run time.
- ↑ By contrast, *"a name binding's context", *"a name binding coming into scope" or *"a name binding going out of scope" are all incorrect—a name binding has scope, while a part of a program has context.
संदर्भ
This article needs additional citations for verification. (December 2008) (Learn how and when to remove this template message) |
- ↑ "Report on the Algorithmic Language Algol 60", 2.7. Quantities, kinds and scopes
- ↑ WG14 N1256 (2007 updated version of the C99 standard), 6.2.1 Scopes of identifiers, 2007-09-07
- ↑ 3.0 3.1 The Go Programming Language Specification: Declarations and scope, Version of Nov 13, 2013
- ↑ 4.0 4.1 4.2 Borning A. CSE 341 -- Lexical and Dynamic Scoping. University of Washington.
- ↑ Crockford, Douglas. "Code Conventions for the JavaScript Programming Language". Retrieved 2015-01-04.
- ↑ Backus, J. W.; Wegstein, J. H.; Van Wijngaarden, A.; Woodger, M.; Bauer, F. L.; Green, J.; Katz, C.; McCarthy, J.; Perlis, A. J.; Rutishauser, H.; Samelson, K.; Vauquois, B. (1960). "Report on the algorithmic language ALGOL 60". Communications of the ACM. 3 (5): 299. doi:10.1145/367236.367262. S2CID 278290.
- ↑ "Functions - Javascript:MDN".
Variables defined inside a function cannot be accessed from anywhere outside the function, because the variable is defined only in the scope of the function. However, a function can access all variables and functions defined inside the scope in which it is defined.
- ↑ "Programming Language Pragmatics", LeBlank-Cook symbol table
- ↑ "A Symbol Table Abstraction to Implement Languages with Explicit Scope Control", LeBlank-Cook, 1983
- ↑ Louis Steele, Guy (August 1982). "An overview of Common LISP". LFP '82: Proceedings of the 1982 ACM Symposium on LISP and Functional Programming: 98–107. doi:10.1145/800068.802140. ISBN 0897910826. S2CID 14517358.
- ↑ Joel, Moses (June 1970). "The Function of FUNCTION in LISP". MIT AI Memo 199. MIT Artificial Intelligence Lab.
- ↑ Steele, Guy Lewis Jr.; Sussman, Gerald Jay (May 1978). "The Art of the Interpreter; or, The Modularity Complex (Parts Zero, One and Two)". MIT AI Memo 453. MIT Artificial Intelligence Lab.
- ↑ Shivers, Olin. "History of T". Paul Graham. Retrieved 5 February 2020.
- ↑ Steele, Guy Lewis Jr. (May 1978). "RABBIT: A Compiler for SCHEME". MIT. hdl:1721.1/6913.
{{cite journal}}
: Cite journal requires|journal=
(help) - ↑ "lexical scope", Computer and Program Organization, Part 3, p. 18, at Google Books, University of Michigan. Engineering Summer Conferences, 1967
- ↑ "lexical scoping", Project MAC Progress Report, Volume 8, p. 80, at Google Books, 1970.
- ↑ 17.0 17.1 Scott 2009, 3.4 Implementing Scope, p. 143.
- ↑ "Scope", XL C/C++ V8.0 for Linux, IBM
- ↑ "Declaring Member Variables (The Java™ Tutorials > Learning the Java Language > Classes and Objects)". docs.oracle.com. Retrieved 19 March 2018.
- ↑ "Controlling Access to Members of a Class (The Java™ Tutorials > Learning the Java Language > Classes and Objects)". docs.oracle.com. Retrieved 19 March 2018.
- ↑ "Everything you need to know about Javascript variable scope", Saurab Parakh, Coding is Cool, 2010-02-08
- ↑ "Annotated ES5". es5.github.io. Retrieved 19 March 2018.
- ↑ "कार्य". MDN Web Docs. Retrieved 19 March 2018.
- ↑ "12.2 Variable Statement", Annotated ECMAScript 5.1, Last updated: 2012-05-28
- ↑ "JavaScript Scoping and Hoisting", Ben Cherry, Adequately Good, 2010-02-08
- ↑ Javascript Closures, Richard Cornford. March 2004
- ↑ "Explaining JavaScript Scope And Closures", Robert Nyman, October 9, 2008
- ↑ Pitman, Kent (December 16, 2007). "The Revised Maclisp Manual (The Pitmanual), Sunday Morning Edition". MACLISP.info. HyperMeta Inc. Declarations and the Compiler, Concept "Variables". Retrieved October 20, 2018.
If the variable to be bound has been declared to be special, the binding is compiled as code to imitate the way the interpreter binds variables
- ↑ Pitman, Kent (December 16, 2007). "The Revised Maclisp Manual (The Pitmanual), Sunday Morning Edition". MACLISP.info. HyperMeta Inc. The Evaluator, Special Form
*FUNCTION
. Retrieved October 20, 2018.*FUNCTION
is intended to help solve the "funarg problem," however it only works in some easy cases. - ↑ Pitman, Kent; et al. (webbed version of ANSI standard X3.226-1994) (1996). "Common Lisp HyperSpec". Lispworks.com. LispWorks Ltd. 1.1.2 History. Retrieved October 20, 2018.
MacLisp improved on the Lisp 1.5 notion of special variables ... The primary influences on Common Lisp were Lisp Machine Lisp, MacLisp, NIL, S-1 Lisp, Spice Lisp, and Scheme.
- ↑ "Programming Language ISLISP, ISLISP Working Draft 23.0" (PDF). ISLISP.info. 11.1 The lexical principle. Retrieved October 20, 2018.
Dynamic bindings are established and accessed by a separate mechanism (i.e.,
defdynamic
,dynamic-let
, anddynamic
). - ↑ "Lexical Binding". EmacsWiki. Retrieved October 20, 2018.
Emacs 24 has optional lexical binding, which can be enabled on a per-buffer basis.
- ↑ "R FAQ". cran.r-project.org. Retrieved 19 March 2018.
- Abelson, Harold; Sussman, Gerald Jay; Sussman, Julie (1996) [1984]. Structure and Interpretation of Computer Programs. Cambridge, MA: MIT Press. ISBN 0-262-51087-1.
- Scott, Michael L. (2009) [2000]. Programming Language Pragmatics (Third ed.). Morgan Kaufmann Publishers. ISBN 978-0-12-374514-9.
- Chapter 3: Names, Scopes, and Bindings, pp. 111–174
- Section 13.4.1: Scripting Languages: Innovative Features: Names and Scopes, pp. 691–699