स्कोप (कंप्यूटर साइंस)
कंप्यूटर प्रोग्रामिंग में, एक नाम बाइंडिंग का स्कोप(किसी इकाई के लिए एक नाम का जुड़ाव, जैसे कि एक वेरिएबल) एक कंप्यूटर प्रोग्राम का भाग है जहां बाइंडिंग बाध्यकारी मान्य है; यानी, जहां इकाई को संदर्भित करने के लिए नाम का उपयोग किया जा सकता है। प्रोग्राम के अन्य भागों में, नाम एक अलग इकाई (इसकी एक अलग बाइंडिंग हो सकती है), या कुछ भी नहीं (यह असीमित हो सकता है) को संदर्भित कर सकता है। स्कोप एक ही नाम को अलग-अलग वस्तुओं को संदर्भित करने की अनुमति देकर नाम टकराव को रोकने में मदद करता है - जब तक कि नामों के अलग-अलग स्कोप हों। एक नाम बाइंडिंग के स्कोप को एक इकाई की दृश्यता के रूप में भी जाना जाता है, विशेष रूप से पुराने या अधिक तकनीकी साहित्य में - यह संदर्भित इकाई के नाम से नहीं परिप्रेक्ष्य से है।
स्कोप शब्द का उपयोग 'सभी' नाम बाइंडिंग के समूह को संदर्भित करने के लिए भी किया जाता है जो किसी प्रोग्राम के एक भाग के भीतर या किसी प्रोग्राम में दिए गए बिंदु पर मान्य होते हैं, जिसे अधिक सही ढंग से 'संदर्भ' या पर्यावरण के रूप में संदर्भित किया जाता है या ।[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. (April 2013) |
प्रतिनिधि भाषाओं के लिए स्कोप के नियम पालन करते हैं।
सी
C में, स्कोप को परंपरागत रूप से लिंकेज (सॉफ्टवेयर) या दृश्यता के रूप में जाना जाता है, विशेष रूप से वेरिएबल्स के लिए। सी वैश्विक स्कोप (बाहरी लिंकेज के रूप में जाना जाता है), इकाई स्कोप या फ़ाइल स्कोप का एक रूप (आंतरिक लिंकेज के रूप में जाना जाता है), और स्थानीय स्कोप (एक समारोह के भीतर) के साथ एक शाब्दिक स्कोप वाली भाषा है; एक फ़ंक्शन स्कोप के भीतर आगे ब्लॉक स्कोप के माध्यम से नेस्ट किया जा सकता है। हालाँकि, मानक C नेस्टेड फ़ंक्शंस का समर्थन नहीं करता है।
एक वेरिएबल का जीवनकाल और दृश्यता उसके भंडारण वर्ग द्वारा निर्धारित की जाती है। सी में तीन प्रकार के जीवन काल हैं: स्थैतिक (प्रोग्राम निष्पादन), स्वचालित (ब्लॉक निष्पादन, ढेर पर आवंटित), और मैनुअल (ढेर पर आवंटित)। वेरिएबल के लिए केवल स्थिर और स्वचालित समर्थित हैं और संकलक द्वारा नियंत्रित किया जाता है, जबकि मैन्युअल रूप से आवंटित मेमोरी को विभिन्न वेरिएबलों में मैन्युअल रूप से ट्रैक किया जाना चाहिए। C में दृश्यता के तीन स्तर हैं: बाहरी लिंकेज (वैश्विक), आंतरिक लिंकेज (मोटे तौर पर फ़ाइल), और ब्लॉक स्कोप (जिसमें फ़ंक्शन निहित हैं); ब्लॉक स्कोप को नेस्टेड किया जा सकता है, और निहित के उपयोग से आंतरिक लिंकेज के विभिन्न स्तरों को संभव है। सी में आंतरिक लिंकेज अनुवाद इकाई (प्रोग्रामिंग) स्तर पर दृश्यता है, अर्थात् सी प्रीप्रोसेसर द्वारा संसाधित किए जाने के बाद एक स्रोत फ़ाइल, विशेष रूप से सभी प्रासंगिक निहित हैं।
C प्रोग्राम को अलग-अलग ऑब्जेक्टफ़ाइल के रूप में संकलित किया जाता है, जो तब एक निष्पादन योग्य या लाइब्रेरी में एक लिंकर (कंप्यूटिंग) के माध्यम से जुड़े होते हैं। इस प्रकार नाम संकल्प संकलक में विभाजित होता है, जो अनुवाद इकाई के भीतर नामों को हल करता है (अधिक शिथिल, संकलन इकाई, लेकिन यह ठीक से एक अलग अवधारणा है), और लिंकर, जो अनुवाद इकाइयों में नामों को हल करता है; आगे की वेरिएबल्चा के लिए लिंकेज (सॉफ्टवेयर) देखें।
सी में, ब्लॉक स्कोप वाले वेरिएबल संदर्भ में प्रवेश करते हैं जब उन्हें घोषित किया जाता है (ब्लॉक के शीर्ष पर नहीं), संदर्भ से बाहर जाएं यदि कोई (गैर-नेस्टेड) फ़ंक्शन ब्लॉक के भीतर कहा जाता है, फ़ंक्शन वापस आने पर संदर्भ में वापस आ जाता है, और ब्लॉक के अंत में संदर्भ से बाहर जाएं। स्वचालित स्थानीय वेरिएबल के मामले में, उन्हें घोषणा पर भी आवंटित किया जाता है और ब्लॉक के अंत में हटा दिया जाता है, जबकि स्थिर स्थानीय वेरिएबल के लिए, उन्हें प्रोग्राम के प्रारंभ में आवंटित किया जाता है और प्रोग्राम की समाप्ति पर हटा दिया जाता है।
निम्नलिखित प्रोग्राम ब्लॉक के माध्यम से संदर्भ भाग में आने वाले ब्लॉक स्कोप के साथ एक वेरिएबल प्रदर्शित करता है, फिर ब्लॉक समाप्त होने पर संदर्भ से बाहर निकलता है (और वास्तव में हटा दिया जाता है): <वाक्यविन्यास प्रकाश लैंग = सी>
- निहित <stdio.h>
पूर्णांक मुख्य (शून्य) {
चार एक्स = 'एम'; प्रिंटफ (% सी \ n, एक्स); { प्रिंटफ (% सी \ n, एक्स); चार एक्स = 'बी'; प्रिंटफ (% सी \ n, एक्स); } प्रिंटफ (% सी \ n, एक्स);
} </वाक्यविन्यास हाइलाइट>
प्रोग्राम आउटपुट: <पूर्व> एम एम बी एम </पूर्व>
सी में स्कोप के अन्य स्तर हैं।[18] फ़ंक्शन प्रोटोटाइप में उपयोग किए जाने वाले वेरिएबल नामों में फ़ंक्शन प्रोटोटाइप दृश्यता होती है, और फ़ंक्शन प्रोटोटाइप के अंत में संदर्भ से बाहर निकलता है। चूंकि नाम का उपयोग नहीं किया गया है, यह संकलन के लिए उपयोगी नहीं है, लेकिन प्रलेखन के लिए उपयोगी हो सकता है। GOTO स्टेटमेंट के लेबल नामों में फंक्शन स्कोप होता है, जबकि स्विच स्टेटमेंट्स के केस लेबल नामों में ब्लॉक स्कोप (स्विच का ब्लॉक) होता है।
सी ++
किसी प्रोग्राम में हम जिन वेरिएबल्स का उपयोग करने का इरादा रखते हैं, उन्हें पहले इसके टाइप स्पेसियर के साथ घोषित किया जाना चाहिए कोड में इंगित करें, जैसा कि हमने पिछले कोड में मुख्य फ़ंक्शन के मुख्य भाग की शुरुआत में किया था जब हम घोषित किया कि a, b, और परिणाम int प्रकार के थे। एक वेरिएबल या तो वैश्विक या स्थानीय स्कोप का हो सकता है। एक वैश्विक वेरिएबल एक वेरिएबल है जिसे मुख्य निकाय में घोषित किया गया है स्रोत कोड, सभी कार्यों के बाहर, जबकि एक स्थानीय वेरिएबल एक फ़ंक्शन या ब्लॉक के शरीर के भीतर घोषित किया जाता है।
आधुनिक संस्करण बेनामी फ़ंक्शन # सी ++ (सी ++ 11 के बाद से) नेस्टेड लेक्सिकल स्कोप।
स्विफ्ट
स्विफ्ट (प्रोग्रामिंग भाषा) में 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] के साथ ब्लॉक स्कोप let
और const
ECMAScript 6 के बाद से कीवर्ड मानक हैं। पूरे ब्लॉक को एक फंक्शन में लपेटकर और फिर इसे निष्पादित करके ब्लॉक स्कोप का उत्पादन किया जा सकता है; इसे तत्काल-आमंत्रित फ़ंक्शन एक्सप्रेशन (IIFE) पैटर्न के रूप में जाना जाता है।
जबकि जावास्क्रिप्ट का स्कोप सरल है - लेक्सिकल, फंक्शन-लेवल - संबद्ध आरंभीकरण और नाम रिज़ॉल्यूशन नियम भ्रम का कारण हैं। सबसे पहले, एक नाम के लिए असाइनमेंट एक नया वैश्विक वेरिएबल बनाने के लिए डिफ़ॉल्ट नहीं है, स्थानीय नहीं। दूसरे, एक नया स्थानीय वेरिएबल बनाने के लिए एक का उपयोग करना चाहिए var
कीवर्ड; वेरिएबल तब मान के साथ फ़ंक्शन के शीर्ष पर बनाया जाता है undefined
और जब असाइनमेंट एक्सप्रेशन तक पहुँच जाता है तो वेरिएबल को उसका मान दिया जाता है:
- प्रारंभकर्ता के साथ एक वेरिएबल को इसके असाइनमेंट एक्सप्रेशन का मान असाइन किया जाता है जब VariableStatement निष्पादित किया जाता है, न कि जब वेरिएबल बनाया जाता है।[24]
इसे वेरिएबल उत्थापन के रूप में जाना जाता है[25]- घोषणा, लेकिन आरंभीकरण नहीं, फ़ंक्शन के शीर्ष पर फहराया जाता है। तीसरा, इनिशियलाइज़ेशन यील्ड से पहले वेरिएबल्स को एक्सेस करना undefined
सिंटैक्स त्रुटि के बजाय। चौथा, फंक्शन डिक्लेरेशन के लिए, डिक्लेरेशन और इनिशियलाइज़ेशन दोनों को फंक्शन के शीर्ष पर फहराया जाता है, वेरिएबल इनिशियलाइज़ेशन के विपरीत। उदाहरण के लिए, निम्न कोड आउटपुट undefined के साथ एक संवाद उत्पन्न करता है, क्योंकि स्थानीय वेरिएबल घोषणा को फहराया जाता है, वैश्विक वेरिएबल को छायांकित किया जाता है, लेकिन आरंभीकरण नहीं होता है, इसलिए उपयोग किए जाने पर वेरिएबल अपरिभाषित होता है:
<वाक्यविन्यास लैंग = जावास्क्रिप्ट>
ए = 1;
समारोह च () {
चेतावनी (ए); वार ए = 2;
} एफ(); </वाक्यविन्यास हाइलाइट>
इसके अलावा, चूंकि फ़ंक्शंस जावास्क्रिप्ट में प्रथम श्रेणी की वस्तुएं हैं और उन्हें प्रायः कॉलबैक के रूप में असाइन किया जाता है या फ़ंक्शन से लौटाया जाता है, जब कोई फ़ंक्शन निष्पादित होता है, तो नाम रिज़ॉल्यूशन इस बात पर निर्भर करता है कि इसे मूल रूप से कहाँ परिभाषित किया गया था (परिभाषा का लेक्सिकल संदर्भ), न कि लेक्सिकल संदर्भया निष्पादन संदर्भ जहां इसे कहा जाता है। जावास्क्रिप्ट में एक विशेष फ़ंक्शन (अधिकांश वैश्विक से अधिकांश स्थानीय तक) के नेस्टेड स्कोप, विशेष रूप से कॉलबैक के रूप में उपयोग किए जाने वाले क्लोजर को कभी-कभी स्कोप चेन के रूप में संदर्भित किया जाता है, जो किसी ऑब्जेक्ट की प्रोटोटाइप श्रृंखला के अनुरूप होता है।
क्लोजर (कंप्यूटर साइंस) जावास्क्रिप्ट में नेस्टेड फ़ंक्शंस का उपयोग करके उत्पादित किया जा सकता है, क्योंकि फ़ंक्शंस प्रथम श्रेणी की वस्तुएं हैं।[26] एक संलग्न फ़ंक्शन से एक नेस्टेड फ़ंक्शन को वापस करने में संलग्न फ़ंक्शन के स्थानीय वेरिएबल निहित होते हैं, जो कि एक बंद करने वाले फ़ंक्शन के (गैर-स्थानीय) लेक्सिकल संदर्भके रूप में होते हैं। उदाहरण के लिए: <वाक्यविन्यास लैंग = जावास्क्रिप्ट> फ़ंक्शन न्यूकाउंटर () {
// एक काउंटर लौटाएं जो कॉल पर बढ़ा हुआ है (0 से शुरू) // और जो अपना नया मान लौटाता है वार ए = 0; var बी = फ़ंक्शन () {ए ++; वापसी ए; }; वापसी बी;
} सी = नया काउंटर (); चेतावनी (सी () + + सी ()); // आउटपुट 1 2 </वाक्यविन्यास हाइलाइट>
कॉलबैक के लिए उपयोग किए जाने के कारण जावास्क्रिप्ट में क्लोजर का प्रायः उपयोग किया जाता है। दरअसल, कॉलबैक के रूप में स्थानीय संदर्भ में किसी फ़ंक्शन का कोई भी हुकिंग या फ़ंक्शन से इसे वापस करने से फ़ंक्शन बॉडी में कोई भी अनबाउंड वेरिएबल होने पर बंद हो जाता है (वर्तमान लेक्सिकल संदर्भ के नेस्टेड स्कोप के आधार पर क्लोजर के संदर्भ में) , या स्कोप चेन); यह आकस्मिक हो सकता है। मापदंडों के आधार पर कॉलबैक बनाते समय, मापदंडों को एक क्लोजर में संग्रहित किया जाना चाहिए, अन्यथा यह गलती से एक क्लोजर बना देगा जो कि संलग्न संदर्भ में वेरिएबल को संदर्भित करता है, जो बदल सकता है।[27] जावास्क्रिप्ट ऑब्जेक्ट्स के गुणों का नाम संकल्प प्रोटोटाइप पेड़ में विरासत पर आधारित है- पेड़ में जड़ के पथ को प्रोटोटाइप श्रृंखला कहा जाता है- और वेरिएबल और कार्यों के नाम संकल्प से अलग होता है।
लिस्प
लिस्प (प्रोग्रामिंग लैंग्वेज) बोलियों के स्कोप के लिए विभिन्न नियम हैं।
मूल लिस्प ने डायनेमिक स्कोप का प्रयोग किया; यह एल्गोल से प्रेरित स्कीम (प्रोग्रामिंग लैंग्वेज) थी, जिसने लिस्प परिवार के लिए स्थिर (लेक्सिकल) गुंजाइश पेश की।
Maclisp ने संकलित कोड में डिफ़ॉल्ट रूप से इंटरप्रेटर और लेक्सिकल स्कोप में डायनेमिक स्कोप का उपयोग किया, हालांकि संकलित कोड डायनामिक बाइंडिंग का उपयोग करके एक्सेस कर सकता है SPECIAL
विशेष वेरिएबल के लिए घोषणाएँ।[28] हालांकि, मैक्लिस्प ने लेक्सिकल बाइंडिंग को आधुनिक भाषाओं में अपेक्षा से अधिक एक अनुकूलन के रूप में माना, और यह क्लोजर (कंप्यूटर प्रोग्रामिंग) सुविधा के साथ नहीं आया, जो आधुनिक लिस्प्स में लेक्सिकल स्कोप की अपेक्षा कर सकता है। एक अलग ऑपरेशन, *FUNCTION
, उस मुद्दे के कुछ हद तक अनाड़ी ढंग से काम करने के लिए उपलब्ध था।[29]
कॉमन लिस्प ने स्कीम (प्रोग्रामिंग लैंग्वेज) से लेक्सिकल स्कोप अपनाया,[30] क्लोजर के रूप में।
ISLISP में साधारण वेरिएबलों के लिए शाब्दिक गुंजाइश है। इसमें डायनेमिक वेरिएबल भी हैं, लेकिन वे सभी स्थितियों में स्पष्ट रूप से चिह्नित हैं; उन्हें ए द्वारा परिभाषित किया जाना चाहिए defdynamic
विशेष रूप, एक से बंधा हुआ dynamic-let
विशेष रूप, और एक स्पष्ट द्वारा पहुँचा dynamic
विशेष रूप।[31]
लिस्प की कुछ अन्य बोलियाँ, जैसे Emacs Lisp, अभी भी डिफ़ॉल्ट रूप से डायनेमिक स्कोप का उपयोग करती हैं। Emacs Lisp में अब प्रति-बफ़र आधार पर शाब्दिक गुंजाइश उपलब्ध है।[32]
पायथन
वेरिएबल्स के लिए, पायथन में फंक्शन स्कोप, इकाई स्कोप और ग्लोबल स्कोप है। स्कोप (फ़ंक्शन, इकाई, या ग्लोबल स्कोप) की शुरुआत में नाम संदर्भ में प्रवेश करते हैं, और जब गैर-नेस्टेड फ़ंक्शन को कॉल किया जाता है या स्कोप समाप्त होता है, तो संदर्भ से बाहर निकल जाते हैं। यदि किसी नाम का उपयोग वेरिएबल इनिशियलाइज़ेशन से पहले किया जाता है, तो यह एक रनटाइम अपवाद उठाता है। यदि एक वेरिएबल को आसानी से एक्सेस किया जाता है (इसे असाइन नहीं किया जाता है), तो नाम रिज़ॉल्यूशन LEGB (लोकल, एनक्लोज़िंग, ग्लोबल, बिल्ट-इन) नियम का पालन करता है, जो नामों को सबसे कम प्रासंगिक संदर्भ में हल करता है। हालाँकि, यदि एक वेरिएबल को सौंपा गया है, तो यह एक वेरिएबल घोषित करने के लिए चूक करता है जिसका स्कोप स्तर (फ़ंक्शन, इकाई या वैश्विक) की शुरुआत में शुरू होता है, न कि असाइनमेंट पर। इन दोनों नियमों को a से ओवरराइड किया जा सकता है global
या nonlocal
(पायथन 3 में) उपयोग से पहले घोषणा, जो मास्किंग गैर-स्थानीय वेरिएबल होने पर भी वैश्विक वेरिएबलों तक पहुँचने की अनुमति देता है, और वैश्विक या गैर-स्थानीय वेरिएबलों को असाइन करता है।
एक साधारण उदाहरण के रूप में, एक फ़ंक्शन एक वेरिएबल को वैश्विक स्कोप में हल करता है:
<वाक्यविन्यास लैंग = पिकॉन>
>>> डीईएफ़ एफ ():
... प्रिंट (एक्स)
...
>>> एक्स = वैश्विक
>>> च()
वैश्विक
</वाक्यविन्यास हाइलाइट>
ध्यान दें कि x
पहले परिभाषित किया गया है f
कहा जाता है, इसलिए कोई त्रुटि नहीं उठाई जाती है, भले ही इसे परिभाषा में इसके संदर्भ के बाद परिभाषित किया गया हो f
. लेक्सिकली यह एक आगे का संदर्भ है, जिसकी अनुमति पायथन में है।
यहाँ असाइनमेंट एक नया स्थानीय वेरिएबल बनाता है, जो वैश्विक वेरिएबल के मान को नहीं बदलता है: <वाक्यविन्यास लैंग = पिकॉन> >>> डीईएफ़ एफ (): ... एक्स = एफ ... प्रिंट (एक्स) ... >>> एक्स = वैश्विक >>> प्रिंट (एक्स) वैश्विक >>> च() एफ >>> प्रिंट (एक्स) वैश्विक </वाक्यविन्यास हाइलाइट>
किसी फ़ंक्शन के भीतर एक वेरिएबल के लिए असाइनमेंट इसे फ़ंक्शन के लिए स्थानीय घोषित करने का कारण बनता है, इसलिए इसका स्कोप संपूर्ण कार्य है, और इस प्रकार इस असाइनमेंट से पहले इसका उपयोग करने से त्रुटि उत्पन्न होती है। यह सी से अलग है, जहां स्थानीय वेरिएबल का स्कोप इसकी घोषणा पर शुरू होता है। यह कोड एक त्रुटि उठाता है: <वाक्यविन्यास लैंग = पिकॉन> >>> डीईएफ़ एफ (): ... प्रिंट (एक्स) ... एक्स = एफ ... >>> एक्स = वैश्विक >>> च() ट्रेसबैक (सबसे हालिया कॉल अंतिम):
फ़ाइल <stdin>, पंक्ति 1, <इकाई> में फ़ाइल <stdin>, पंक्ति 2, f में
अनबाउंडलोकल एरर: स्थानीय वेरिएबल 'एक्स' असाइनमेंट से पहले संदर्भित </वाक्यविन्यास हाइलाइट>
डिफ़ॉल्ट नाम रिज़ॉल्यूशन नियमों को इसके साथ ओवरराइड किया जा सकता है global
या nonlocal
(पायथन 3 में) कीवर्ड। नीचे दिए गए कोड में, global x
में घोषणा g
मतलब कि x
वैश्विक वेरिएबल को हल करता है। इस प्रकार इसे एक्सेस किया जा सकता है (जैसा कि इसे पहले ही परिभाषित किया जा चुका है), और असाइनमेंट एक नया स्थानीय वैरिएबल घोषित करने के बजाय ग्लोबल वैरिएबल को असाइन करता है। ध्यान दें कि नहीं global
में घोषणा की आवश्यकता है f
-चूंकि यह वेरिएबल को निर्दिष्ट नहीं करता है, यह वैश्विक वेरिएबल को हल करने के लिए चूक करता है।
<वाक्यविन्यास लैंग = पिकॉन>
>>> डीईएफ़ एफ ():
... प्रिंट (एक्स)
...
>>> डीईएफ़ जी ():
... ग्लोबल एक्स
... प्रिंट (एक्स)
... एक्स = जी
...
>>> एक्स = वैश्विक
>>> च()
वैश्विक
>>> जी ()
वैश्विक
>>> च()
जी
</वाक्यविन्यास हाइलाइट>
global
नेस्टेड कार्यों के लिए भी प्रयोग किया जा सकता है। एक गैर-स्थानीय वेरिएबल की उपस्थिति में एक वैश्विक वेरिएबल के लिए असाइनमेंट की अनुमति देने के अलावा, इसका उपयोग वैश्विक वेरिएबल तक पहुंचने के लिए भी किया जा सकता है:
<वाक्यविन्यास लैंग = पिकॉन>
>>> डीईएफ़ एफ ():
... डीईएफ़ जी ():
... ग्लोबल एक्स
... प्रिंट (एक्स)
... एक्स = एफ
... जी()
...
>>> एक्स = वैश्विक
>>> च()
वैश्विक
</वाक्यविन्यास हाइलाइट>
नेस्टेड कार्यों के लिए भी है nonlocal
घोषणा, एक गैर-स्थानीय वेरिएबल को असाइन करने के लिए, उपयोग करने के समान global
एक अवांछित कार्य में:
<वाक्यविन्यास लैंग = पिकॉन>
>>> डीईएफ़ एफ ():
... डीईएफ़ जी ():
... नॉनलोकल एक्स # पायथन 3 केवल
... एक्स = जी
... एक्स = एफ
... जी()
... प्रिंट (एक्स)
...
>>> एक्स = वैश्विक
>>> च()
जी
>>> प्रिंट (एक्स)
वैश्विक
</वाक्यविन्यास हाइलाइट>
आर
R (प्रोग्रामिंग लैंग्वेज) एक लेक्सिकली स्कोप्ड लैंग्वेज है, S (प्रोग्रामिंग लैंग्वेज) के अन्य कार्यान्वयनों के विपरीत, जहां मुक्त वेरिएबल के मान वैश्विक वेरिएबल के एक सेट द्वारा निर्धारित किए जाते हैं, जबकि R में वे उस संदर्भ द्वारा निर्धारित किए जाते हैं जिसमें फ़ंक्शन बनाया गया था। .[33] स्कोप के संदर्भों को विभिन्न प्रकार की विशेषताओं (जैसे parent.frame()
) जो प्रोग्रामर की इच्छा के अनुसार डायनेमिक स्कोप के अनुभव का अनुकरण कर सकता है।
कोई ब्लॉक स्कोप नहीं है: <वाक्यविन्यास लैंग = आर> एक <- 1 {
एक <- 2
} संदेश (ए)
- 2
</वाक्यविन्यास हाइलाइट>
कार्यों के पास उस स्कोप तक पहुंच है जिसमें वे बनाए गए थे: <वाक्यविन्यास लैंग = आर> एक <- 1 च <- समारोह () {
संदेश (ए)
} एफ()
- 1
</वाक्यविन्यास हाइलाइट>
किसी फ़ंक्शन के भीतर बनाए गए या संशोधित वेरिएबल वहां रहते हैं: <वाक्यविन्यास लैंग = आर> एक <- 1 च <- समारोह () {
संदेश (ए) एक <- 2 संदेश (ए)
} एफ()
- 1
- 2
संदेश (ए)
- 1
</वाक्यविन्यास हाइलाइट>
किसी फ़ंक्शन के भीतर बनाए या संशोधित किए गए वेरिएबल तब तक बने रहते हैं जब तक कि स्कोपको संलग्न करने के लिए स्पष्ट रूप से अनुरोध नहीं किया जाता है: <वाक्यविन्यास लैंग = आर> एक <- 1 च <- समारोह () {
संदेश (ए) एक <<- 2 संदेश (ए)
} एफ()
- 1
- 2
संदेश (ए)
- 2
</वाक्यविन्यास हाइलाइट>
हालाँकि R में डिफ़ॉल्ट रूप से लेक्सिकल स्कोप है, फंक्शन स्कोप्स को बदला जा सकता है: <वाक्यविन्यास लैंग = आर> एक <- 1 च <- समारोह () {
संदेश (ए)
} my_env <- new.env () my_env$a <- 2 एफ()
- 1
पर्यावरण (च) <- my_env एफ()
- 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