स्कोप (कंप्यूटर साइंस): Difference between revisions
No edit summary |
No edit summary |
||
Line 1: | Line 1: | ||
{{Short description|Part of a computer program where a given name binding is valid}} | {{Short description|Part of a computer program where a given name binding is valid}} | ||
[[कंप्यूटर प्रोग्राम|कंप्यूटर प्रोग्रामिंग]] में, एक [[नाम बंधन|नाम बाइंडिंग]] का कार्यक्षेत्र(किसी इकाई के लिए एक नाम का जुड़ाव, जैसे कि एक [[चर (प्रोग्रामिंग)|वेरिएबल]]) एक कंप्यूटर प्रोग्राम का हिस्सा है जहां बाइंडिंग बाध्यकारी मान्य है; यानी, जहां इकाई को संदर्भित करने के लिए नाम का उपयोग किया जा सकता है। कार्यक्रम के अन्य भागों में, नाम एक अलग इकाई (इसकी एक अलग बाइंडिंग हो सकती है), | [[कंप्यूटर प्रोग्राम|कंप्यूटर प्रोग्रामिंग]] में, एक [[नाम बंधन|नाम बाइंडिंग]] का कार्यक्षेत्र(किसी इकाई के लिए एक नाम का जुड़ाव, जैसे कि एक [[चर (प्रोग्रामिंग)|वेरिएबल]]) एक कंप्यूटर प्रोग्राम का हिस्सा है जहां बाइंडिंग बाध्यकारी मान्य है; यानी, जहां इकाई को संदर्भित करने के लिए नाम का उपयोग किया जा सकता है। कार्यक्रम के अन्य भागों में, नाम एक अलग इकाई (इसकी एक अलग बाइंडिंग हो सकती है), या कुछ भी नहीं (यह अनबाउंड हो सकता है) को संदर्भित कर सकता '''है।''' दायरा एक ही नाम को अलग-अलग वस्तुओं को संदर्भित करने की अनुमति देकर नाम टकराव को रोकने में मदद करता है - जब तक कि नामों के अलग-अलग दायरे हों। एक नाम बाइंडिंग के दायरे को एक इकाई की दृश्यता के रूप में भी जाना जाता है, विशेष रूप से पुराने या अधिक तकनीकी साहित्य में - यह संदर्भित इकाई के परिप्रेक्ष्य से है, संदर्भित नाम से नहीं। | ||
स्कोप शब्द का उपयोग 'सभी' नाम बाइंडिंग के सेट को संदर्भित करने के लिए भी किया जाता है जो किसी प्रोग्राम के एक भाग के भीतर या किसी प्रोग्राम में दिए गए बिंदु पर मान्य होते हैं, जिसे अधिक सही ढंग से 'संदर्भ' के रूप में संदर्भित किया जाता है या ''पर्यावरण''।{{efn|1=See [[#Definition|definition]] for meaning of "scope" versus "context".}} | स्कोप शब्द का उपयोग 'सभी' नाम बाइंडिंग के सेट को संदर्भित करने के लिए भी किया जाता है जो किसी प्रोग्राम के एक भाग के भीतर या किसी प्रोग्राम में दिए गए बिंदु पर मान्य होते हैं, जिसे अधिक सही ढंग से 'संदर्भ' के रूप में संदर्भित किया जाता है या ''पर्यावरण''।{{efn|1=See [[#Definition|definition]] for meaning of "scope" versus "context".}} |
Revision as of 17:30, 1 March 2023
कंप्यूटर प्रोग्रामिंग में, एक नाम बाइंडिंग का कार्यक्षेत्र(किसी इकाई के लिए एक नाम का जुड़ाव, जैसे कि एक वेरिएबल) एक कंप्यूटर प्रोग्राम का हिस्सा है जहां बाइंडिंग बाध्यकारी मान्य है; यानी, जहां इकाई को संदर्भित करने के लिए नाम का उपयोग किया जा सकता है। कार्यक्रम के अन्य भागों में, नाम एक अलग इकाई (इसकी एक अलग बाइंडिंग हो सकती है), या कुछ भी नहीं (यह अनबाउंड हो सकता है) को संदर्भित कर सकता है। दायरा एक ही नाम को अलग-अलग वस्तुओं को संदर्भित करने की अनुमति देकर नाम टकराव को रोकने में मदद करता है - जब तक कि नामों के अलग-अलग दायरे हों। एक नाम बाइंडिंग के दायरे को एक इकाई की दृश्यता के रूप में भी जाना जाता है, विशेष रूप से पुराने या अधिक तकनीकी साहित्य में - यह संदर्भित इकाई के परिप्रेक्ष्य से है, संदर्भित नाम से नहीं।
स्कोप शब्द का उपयोग 'सभी' नाम बाइंडिंग के सेट को संदर्भित करने के लिए भी किया जाता है जो किसी प्रोग्राम के एक भाग के भीतर या किसी प्रोग्राम में दिए गए बिंदु पर मान्य होते हैं, जिसे अधिक सही ढंग से 'संदर्भ' के रूप में संदर्भित किया जाता है या पर्यावरण।[lower-alpha 1] सच पूछिये तो[lower-alpha 2] और अभ्यास में अधिकांश प्रोग्रामिंग भाषाओं के लिए, एक प्रोग्राम का हिस्सा स्रोत कोड (टेक्स्ट का क्षेत्र) के एक हिस्से को संदर्भित करता है, और इसे लेक्सिकल स्कोप के रूप में जाना जाता है। हालांकि, कुछ भाषाओं में, प्रोग्राम का हिस्सा रनटाइम (प्रोग्राम जीवनचक्र चरण) (निष्पादन (कंप्यूटिंग) के दौरान समय अवधि) के एक हिस्से को संदर्भित करता है, और इसे गतिशील दायरे के रूप में जाना जाता है। ये दोनों शब्द कुछ हद तक भ्रामक हैं - वे तकनीकी शब्दों का दुरुपयोग करते हैं, जैसा कि #परिभाषा में चर्चा की गई है - लेकिन भेद स्वयं सटीक और सटीक है, और ये मानक संबंधित शब्द हैं। लेक्सिकल स्कोप इस लेख का मुख्य फोकस है, डायनेमिक स्कोप को लेक्सिकल स्कोप के विपरीत समझा जाता है।
ज्यादातर मामलों में, लेक्सिकल स्कोप पर आधारित नाम रिज़ॉल्यूशन उपयोग करने और लागू करने के लिए अपेक्षाकृत सरल है, क्योंकि उपयोग में कोई व्यक्ति स्रोत कोड में पीछे की ओर पढ़ सकता है, यह निर्धारित करने के लिए कि किस इकाई को एक नाम संदर्भित करता है, और प्रोग्रामिंग भाषा कार्यान्वयन में कोई एक सूची बनाए रख सकता है किसी प्रोग्राम को संकलन या दुभाषिया (कंप्यूटिंग) करते समय नाम और संदर्भ। नाम मास्किंग, आगे की घोषणा और चर उत्थापन में कठिनाइयाँ उत्पन्न होती हैं, जबकि विशेष रूप से क्लोजर (कंप्यूटर प्रोग्रामिंग) में गैर-स्थानीय चर के साथ काफी सूक्ष्मताएँ उत्पन्न होती हैं।
परिभाषा
एक नाम (पहचानकर्ता) के (लेक्सिकल) स्कोप की सख्त परिभाषा स्पष्ट है: लेक्सिकल स्कोप स्रोत कोड का वह भाग है जिसमें एक इकाई के साथ एक नाम का बंधन लागू होता है। यह ALGOL 60 के विनिर्देशन में इसकी 1960 की परिभाषा से वस्तुतः अपरिवर्तित है। प्रतिनिधि भाषा विनिर्देशों का पालन करें:
- एल्गोल 60 (1960)[1]
- निम्न प्रकार की मात्राएँ प्रतिष्ठित हैं: सरल चर, सरणियाँ, लेबल, स्विच और प्रक्रियाएँ। मात्रा का दायरा बयानों और अभिव्यक्तियों का समूह है जिसमें उस मात्रा से जुड़े पहचानकर्ता की घोषणा मान्य है।
- सी (प्रोग्रामिंग भाषा) (2007)[2]
- एक पहचानकर्ता किसी वस्तु को निरूपित कर सकता है; एक समारोह; एक टैग या संरचना, संघ, या गणना का सदस्य; एक टाइपिफ़ नाम; एक लेबल नाम; एक मैक्रो नाम; या एक मैक्रो पैरामीटर। एक ही पहचानकर्ता कार्यक्रम में विभिन्न बिंदुओं पर विभिन्न संस्थाओं को निरूपित कर सकता है। [...] प्रत्येक अलग इकाई के लिए जिसे एक पहचानकर्ता निर्दिष्ट करता है, पहचानकर्ता दिखाई देता है (अर्थात, इसका उपयोग किया जा सकता है) केवल प्रोग्राम टेक्स्ट के एक क्षेत्र के भीतर जिसे इसका दायरा कहा जाता है।
- जाओ (प्रोग्रामिंग भाषा) (2013)[3]
- एक घोषणा एक गैर-खाली पहचानकर्ता को एक स्थिर, प्रकार, चर, फ़ंक्शन, लेबल या पैकेज से बांधती है। [...] एक घोषित पहचानकर्ता का दायरा स्रोत पाठ की सीमा है जिसमें पहचानकर्ता निर्दिष्ट स्थिरांक, प्रकार, चर, कार्य, लेबल या पैकेज को दर्शाता है।
आमतौर पर स्कोप से तात्पर्य तब होता है जब कोई दिया गया नाम किसी दिए गए वेरिएबल (प्रोग्रामिंग) को संदर्भित कर सकता है - जब एक घोषणा (कंप्यूटर प्रोग्रामिंग) का प्रभाव होता है - लेकिन यह अन्य संस्थाओं पर भी लागू हो सकता है, जैसे कि कार्य, प्रकार, वर्ग, लेबल (कंप्यूटर विज्ञान) , स्थिरांक और गणन।
लेक्सिकल स्कोप बनाम डायनेमिक स्कोप
दायरे में एक मूलभूत अंतर यह है कि किसी कार्यक्रम का क्या मतलब है। लेक्सिकल स्कोप (जिसे स्टैटिक स्कोप भी कहा जाता है) वाली भाषाओं में, नाम रिज़ॉल्यूशन स्रोत कोड और लेक्सिकल कॉन्टेक्स्ट (जिसे स्टेटिक कॉन्टेक्स्ट भी कहा जाता है) में स्थान पर निर्भर करता है, जिसे नामित चर द्वारा परिभाषित किया गया है या कार्य परिभाषित किया गया है। इसके विपरीत, डायनेमिक स्कोप वाली भाषाओं में नाम का समाधान कार्यक्रम की स्थिति पर निर्भर करता है जब नाम का सामना किया जाता है जो निष्पादन संदर्भ (जिसे रनटाइम संदर्भ, कॉलिंग संदर्भ या 'भी कहा जाता है) द्वारा निर्धारित किया जाता है। 'गतिशील संदर्भ)। व्यवहार में, शाब्दिक दायरे के साथ स्थानीय शाब्दिक संदर्भ की खोज करके एक नाम का समाधान किया जाता है, फिर यदि वह विफल हो जाता है, तो बाहरी शाब्दिक संदर्भ की खोज करके, और इसी तरह; जबकि डायनेमिक स्कोप के साथ, स्थानीय निष्पादन संदर्भ को खोजकर एक नाम का समाधान किया जाता है, फिर यदि वह विफल हो जाता है, तो बाहरी निष्पादन संदर्भ की खोज करके, और इसी तरह, कॉल स्टैक को आगे बढ़ाया जाता है।[4]
अधिकांश आधुनिक भाषाएं चर और कार्यों के लिए लेक्सिकल स्कोप का उपयोग करती हैं, हालांकि डायनेमिक स्कोप का उपयोग कुछ भाषाओं में किया जाता है, विशेष रूप से लिस्प की कुछ बोलियों, कुछ स्क्रिप्टिंग भाषाओं और कुछ टेम्पलेट भाषाओं में। [lower-alpha 3] पर्ल 5 लेक्सिकल और डायनेमिक स्कोप दोनों प्रदान करता है। यहां तक कि शाब्दिक रूप से दायरे वाली भाषाओं में, बंद करने की गुंजाइश (कंप्यूटर विज्ञान) असंबद्ध लोगों के लिए भ्रमित करने वाली हो सकती है,[citation needed] क्योंकि ये शाब्दिक संदर्भ पर निर्भर करते हैं जहां क्लोजर को परिभाषित किया गया है, न कि जहां इसे कहा जाता है।
लेक्सिकल रिज़ॉल्यूशन को संकलन समय पर निर्धारित किया जा सकता है, और इसे शुरुआती बाइंडिंग के रूप में भी जाना जाता है, जबकि डायनेमिक रिज़ॉल्यूशन को सामान्य रूप से केवल रन टाइम (प्रोग्राम जीवनचक्र चरण) पर निर्धारित किया जा सकता है, और इस प्रकार इसे लेट बाइंडिंग के रूप में जाना जाता है।
संबंधित अवधारणाएं
ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग में, गतिशील प्रेषण रनटाइम पर एक ऑब्जेक्ट विधि (कंप्यूटर प्रोग्रामिंग) का चयन करता है, हालांकि वास्तविक नाम बाइंडिंग संकलन समय पर किया जाता है या रन टाइम भाषा पर निर्भर करता है। मैक्रो (कंप्यूटर विज्ञान) में डी फैक्टो डायनेमिक स्कोप आम है, जो सीधे नाम रिज़ॉल्यूशन नहीं करते हैं, बल्कि जगह में विस्तार करते हैं।
AngularJS#Scope जैसे कुछ प्रोग्रामिंग फ्रेमवर्क इस लेख में उपयोग किए जाने वाले तरीके से पूरी तरह से अलग अर्थ के लिए स्कोप शब्द का उपयोग करते हैं। उन रूपरेखाओं में दायरा केवल प्रोग्रामिंग भाषा का एक वस्तु है जिसका वे उपयोग करते हैं (एंगुलरजेएस के मामले में जावास्क्रिप्ट) जिसका प्रयोग ढांचे द्वारा कुछ तरीकों से गतिशील दायरे का अनुकरण करने के लिए किया जाता है जो इसके चर के लिए व्याख्यात्मक दायरे का उपयोग करता है। वे AngularJS#Scope स्वयं संदर्भ में हो सकते हैं या संदर्भ में नहीं (शब्द के सामान्य अर्थ का उपयोग करके) कार्यक्रम के किसी भी भाग में, किसी अन्य वस्तु की तरह भाषा के चर दायरे के सामान्य नियमों का पालन करते हुए, और अपने स्वयं के वंशानुक्रम का उपयोग करते हुए (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग) और ट्रांसक्लुजन नियम। AngularJS के संदर्भ में, कभी-कभी भ्रम से बचने के लिए $ गुंजाइश (डॉलर चिह्न के साथ) शब्द का उपयोग किया जाता है, लेकिन चर नामों में डॉलर चिह्न का उपयोग अक्सर स्टाइल गाइड द्वारा हतोत्साहित किया जाता है।[5]
प्रयोग
स्कोप नाम रिज़ॉल्यूशन (प्रोग्रामिंग लैंग्वेज) का एक महत्वपूर्ण घटक है,[lower-alpha 4] जो बदले में प्रोग्रामिंग भाषाओं के औपचारिक शब्दार्थ के लिए मौलिक है। नाम संकल्प (दायरे सहित) प्रोग्रामिंग भाषाओं के बीच भिन्न होता है, और प्रोग्रामिंग भाषा के भीतर, इकाई के प्रकार से भिन्न होता है; स्कोप के नियमों को स्कोप नियम (या स्कोपिंग नियम) कहा जाता है। मॉड्यूलर प्रोग्रामिंग में नामस्थान के साथ, स्कोप नियम महत्वपूर्ण हैं, इसलिए प्रोग्राम के एक हिस्से में बदलाव एक असंबंधित हिस्से को नहीं तोड़ता है।
सिंहावलोकन
कार्यक्षेत्र पर चर्चा करते समय, तीन बुनियादी अवधारणाएँ होती हैं: कार्यक्षेत्र, सीमा और संदर्भ। विशेष रूप से स्कोप और संदर्भ अक्सर भ्रमित होते हैं: स्कोप एक नाम बाध्यकारी की संपत्ति है, जबकि संदर्भ प्रोग्राम के एक हिस्से की संपत्ति है, जो या तो स्रोत कोड का एक हिस्सा है (शाब्दिक संदर्भ या स्थिर संदर्भ) या रन का एक हिस्सा समय (कार्यक्रम जीवनचक्र चरण) (निष्पादन संदर्भ, रनटाइम संदर्भ, कॉलिंग संदर्भ या गतिशील संदर्भ)। निष्पादन संदर्भ में लेक्सिकल संदर्भ (वर्तमान निष्पादन बिंदु पर) और अतिरिक्त रनटाइम स्थिति जैसे कॉल स्टैक शामिल हैं।[lower-alpha 5] सख्ती से बोलना, निष्पादन के दौरान एक प्रोग्राम विभिन्न नाम बाइंडिंग के स्कोप में प्रवेश करता है और बाहर निकलता है, और निष्पादन के एक बिंदु पर नाम बाइंडिंग संदर्भ में है या संदर्भ में नहीं है, इसलिए नाम बाइंडिंग संदर्भ में आती है या संदर्भ से बाहर हो जाती है क्योंकि प्रोग्राम निष्पादन प्रवेश करता है या बाहर निकलता है क्षेत्र।[lower-alpha 6] हालाँकि, व्यवहार में उपयोग बहुत कम है।
स्कोप एक स्रोत-कोड स्तर की अवधारणा है, और नाम बाइंडिंग की एक संपत्ति है, विशेष रूप से चर या फ़ंक्शन नाम बाइंडिंग - स्रोत कोड में नाम प्रोग्राम में संस्थाओं के लिए संदर्भ (कंप्यूटर विज्ञान) हैं - और एक संकलक के व्यवहार का हिस्सा है या एक भाषा का दुभाषिया। जैसे, स्कोप के मुद्दे सूचक (कंप्यूटर प्रोग्रामिंग) के समान होते हैं, जो एक प्रकार का संदर्भ है जो आमतौर पर कार्यक्रमों में उपयोग किया जाता है। एक चर के मान का उपयोग करना जब नाम संदर्भ में है, लेकिन चर अप्रारंभीकृत है, एक जंगली सूचक को डेरेफ़रिंग (मूल्य तक पहुँचने) के अनुरूप है, क्योंकि यह अपरिभाषित है। हालाँकि, जब तक वे संदर्भ से बाहर नहीं जाते, तब तक चर नष्ट नहीं होते हैं, झूलने वाले सूचक का एनालॉग मौजूद नहीं होता है।
वैरिएबल जैसी संस्थाओं के लिए, स्कोप वस्तु जीवनकाल का एक सबसेट है (जिसे वेरिएबल (प्रोग्रामिंग) # स्कोप और हद के रूप में भी जाना जाता है) - एक नाम केवल एक वेरिएबल को संदर्भित कर सकता है जो मौजूद है (संभवतः अपरिभाषित मान के साथ), लेकिन मौजूद वेरिएबल्स नहीं हैं आवश्यक रूप से दृश्यमान: एक चर मौजूद हो सकता है लेकिन दुर्गम हो सकता है (मान संग्रहीत है लेकिन किसी दिए गए संदर्भ में संदर्भित नहीं है), या सुलभ है लेकिन दिए गए नाम के माध्यम से नहीं है, जिस स्थिति में यह संदर्भ में नहीं है (कार्यक्रम दायरे से बाहर है) नाम का)। अन्य मामलों में जीवनकाल अप्रासंगिक है - एक लेबल (स्रोत कोड में नाम की स्थिति) कार्यक्रम के साथ आजीवन समान है (सांख्यिकीय रूप से संकलित भाषाओं के लिए), लेकिन संदर्भ में हो सकता है या कार्यक्रम में दिए गए बिंदु पर नहीं हो सकता है, और इसी तरह स्थिर चर के लिए —एक स्थिर वैश्विक चर पूरे कार्यक्रम के संदर्भ में है, जबकि एक स्थिर स्थानीय चर केवल एक समारोह या अन्य स्थानीय संदर्भ के संदर्भ में है, लेकिन दोनों के पास कार्यक्रम के पूरे रन का जीवनकाल है।
यह निर्धारित करना कि किस इकाई का नाम संदर्भित है, नाम संकल्प (प्रोग्रामिंग भाषा) या नाम बाध्यकारी (विशेष रूप से ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग में) के रूप में जाना जाता है, और भाषाओं के बीच भिन्न होता है। एक नाम दिया गया है, भाषा (ठीक है, संकलक या दुभाषिया) उन सभी संस्थाओं की जाँच करती है जो मैचों के संदर्भ में हैं; अस्पष्टता के मामले में (एक ही नाम वाली दो संस्थाएँ, जैसे कि एक ही नाम के साथ एक वैश्विक और स्थानीय चर), उन्हें अलग करने के लिए नाम समाधान नियमों का उपयोग किया जाता है। सबसे अधिक बार, नाम रिज़ॉल्यूशन आंतरिक-से-बाहरी संदर्भ नियम पर निर्भर करता है, जैसे कि पायथन एलईजीबी (लोकल, एनक्लोजिंग, ग्लोबल, बिल्ट-इन) नियम: नाम निहित रूप से सबसे कम प्रासंगिक संदर्भ को हल करता है। कुछ मामलों में नाम संकल्प स्पष्ट रूप से निर्दिष्ट किया जा सकता है, जैसे कि द्वारा global
और nonlocal
पायथन में कीवर्ड; अन्य मामलों में डिफ़ॉल्ट नियमों को ओवरराइड नहीं किया जा सकता है।
जब दो समान नाम एक ही समय में संदर्भ में होते हैं, विभिन्न संस्थाओं का जिक्र करते हुए, एक कहता है कि नाम मास्किंग हो रहा है, जहां उच्च-प्राथमिकता वाला नाम (आमतौर पर अंतरतम) निम्न-प्राथमिकता वाले नाम को मास्क कर रहा है। चर के स्तर पर, इसे चर छायांकन के रूप में जाना जाता है। मास्किंग से तार्किक त्रुटियों की संभावना के कारण, कुछ भाषाएँ मास्किंग को अस्वीकार या हतोत्साहित करती हैं, त्रुटि उत्पन्न करती हैं या संकलन समय या रन टाइम पर चेतावनी देती हैं।
विभिन्न प्रोग्रामिंग भाषाओं में विभिन्न प्रकार की घोषणाओं और नामों के लिए विभिन्न दायरे के नियम हैं। इस तरह के दायरे के नियमों का प्रोग्रामिंग भाषाओं के औपचारिक शब्दार्थ पर और इसके परिणामस्वरूप, कार्यक्रमों के व्यवहार और शुद्धता पर बड़ा प्रभाव पड़ता है। C++ जैसी भाषाओं में, एक अनबाउंड वेरिएबल तक पहुँचने के लिए अच्छी तरह से परिभाषित शब्दार्थ नहीं होता है और इसके परिणामस्वरूप अपरिभाषित व्यवहार हो सकता है, जो झूलने वाले सूचक के संदर्भ में होता है; और उनके दायरे से बाहर उपयोग की जाने वाली घोषणाएं या नाम सिंटैक्स त्रुटियां उत्पन्न करेंगे।
स्कोप अक्सर अन्य भाषा निर्माणों से बंधे होते हैं और निहित रूप से निर्धारित होते हैं, लेकिन कई भाषाएँ विशेष रूप से स्कोप को नियंत्रित करने के लिए भी निर्माण की पेशकश करती हैं।
दायरे का स्तर
स्कोप एक एक्सप्रेशन जितना कम से लेकर पूरे प्रोग्राम तक भिन्न हो सकता है, बीच में कई संभावित ग्रेडेशन के साथ। सबसे सरल दायरा नियम वैश्विक दायरा है—पूरे कार्यक्रम में सभी निकाय दिखाई देते हैं। सबसे बुनियादी मॉड्यूलर स्कोप नियम दो-स्तरीय स्कोप है, प्रोग्राम में कहीं भी वैश्विक स्कोप और फ़ंक्शन के भीतर स्थानीय स्कोप। अधिक परिष्कृत मॉड्यूलर प्रोग्रामिंग एक अलग मॉड्यूल स्कोप की अनुमति देता है, जहां मॉड्यूल के भीतर नाम दिखाई देते हैं (मॉड्यूल के लिए निजी) लेकिन इसके बाहर दिखाई नहीं देते। किसी फ़ंक्शन के भीतर, कुछ भाषाएँ, जैसे कि C, ब्लॉक स्कोप को किसी फ़ंक्शन के सबसेट तक सीमित करने की अनुमति देती हैं; अन्य, विशेष रूप से कार्यात्मक भाषाएं, अभिव्यक्ति के दायरे की अनुमति देती हैं, एक अभिव्यक्ति के दायरे को प्रतिबंधित करने के लिए। अन्य स्कोप में फ़ाइल स्कोप (विशेष रूप से C में) शामिल है जो मॉड्यूल स्कोप के समान व्यवहार करता है, और फ़ंक्शंस के बाहर ब्लॉक स्कोप (विशेष रूप से पर्ल में)।
एक सूक्ष्म मुद्दा ठीक उसी समय होता है जब कोई दायरा शुरू और समाप्त होता है। कुछ भाषाओं में, जैसे सी, एक नाम का दायरा नाम की घोषणा से शुरू होता है, और इस प्रकार किसी दिए गए ब्लॉक में घोषित अलग-अलग नामों के अलग-अलग दायरे हो सकते हैं। इसके लिए उपयोग से पहले कार्यों को घोषित करने की आवश्यकता होती है, हालांकि जरूरी नहीं कि उन्हें परिभाषित किया जाए, और कुछ मामलों में विशेष रूप से पारस्परिक पुनरावृत्ति के लिए आगे की घोषणा की आवश्यकता होती है। अन्य भाषाओं में, जैसे कि पायथन, एक नाम का दायरा प्रासंगिक ब्लॉक की शुरुआत में शुरू होता है जहां नाम घोषित किया जाता है (जैसे कि फ़ंक्शन की शुरुआत), चाहे वह कहीं भी परिभाषित हो, इसलिए किसी दिए गए ब्लॉक के सभी नामों में एक ही गुंजाइश। जावास्क्रिप्ट में, घोषित नाम का दायरा let
या const
नाम की घोषणा से शुरू होता है, और घोषित नाम का दायरा var
समारोह के प्रारंभ में शुरू होता है जहां नाम घोषित किया जाता है, जिसे चर उत्थापन के रूप में जाना जाता है। अपरिभाषित मान वाले संदर्भ में नामों का व्यवहार भिन्न होता है: पायथन में अपरिभाषित नामों के उपयोग से रनटाइम त्रुटि उत्पन्न होती है, जबकि जावास्क्रिप्ट में अपरिभाषित नामों के साथ घोषित किया जाता है var
पूरे समारोह में प्रयोग करने योग्य हैं क्योंकि वे निहित रूप से मूल्य के लिए बाध्य हैं undefined
.
अभिव्यक्ति का दायरा
नेम बाइंडिंग का स्कोप एक अभिव्यक्ति (कंप्यूटर विज्ञान) है, जिसे एक्सप्रेशन स्कोप के नाम से जाना जाता है। अभिव्यक्ति का दायरा कई भाषाओं में उपलब्ध है, विशेष रूप से कार्यात्मक प्रोग्रामिंग भाषाएं जो लेट-एक्सप्रेशन नामक सुविधा प्रदान करती हैं, जिससे घोषणा का दायरा एकल अभिव्यक्ति हो जाता है। यह सुविधाजनक है अगर, उदाहरण के लिए, गणना के लिए एक मध्यवर्ती मान की आवश्यकता होती है। उदाहरण के लिए, मानक एमएल में, यदि 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 में) में सहायक वेरिएबल्स में एक्सप्रेशन स्कोप होता है।
सी में, फ़ंक्शन प्रोटोटाइप में वेरिएबल नामों में अभिव्यक्ति का दायरा होता है, जिसे इस संदर्भ में फ़ंक्शन प्रोटोकॉल स्कोप के रूप में जाना जाता है। जैसा कि प्रोटोटाइप में वेरिएबल नामों को संदर्भित नहीं किया जाता है (वे वास्तविक परिभाषा में भिन्न हो सकते हैं) - वे सिर्फ डमी हैं - इन्हें अक्सर छोड़ दिया जाता है, हालांकि उनका उपयोग प्रलेखन बनाने के लिए किया जा सकता है, उदाहरण के लिए।
ब्लॉक स्कोप
नाम बाइंडिंग का स्कोप एक ब्लॉक (प्रोग्रामिंग) है, जिसे ब्लॉक स्कोप के रूप में जाना जाता है। ब्लॉक का दायरा कई में उपलब्ध है, लेकिन सभी में नहीं, ब्लॉक-संरचित प्रोग्रामिंग भाषाओं में। यह ALGOL 60 के साथ शुरू हुआ, जहां [ई] बहुत घोषणा ... केवल उस ब्लॉक के लिए मान्य है। ,[6] और आज विशेष रूप से पास्कल (प्रोग्रामिंग भाषा) और सी (प्रोग्रामिंग भाषा) परिवारों और परंपराओं में भाषाओं से जुड़ा हुआ है। अक्सर यह ब्लॉक एक फ़ंक्शन के भीतर समाहित होता है, इस प्रकार एक फ़ंक्शन के एक भाग के दायरे को सीमित करता है, लेकिन कुछ मामलों में, जैसे कि पर्ल, ब्लॉक फ़ंक्शन के भीतर नहीं हो सकता है।
<वाक्यविन्यास लैंग = सी> अहस्ताक्षरित int योग_of_squares (स्थिरांक अहस्ताक्षरित int N) {
अहस्ताक्षरित int ret = 0; के लिए (अहस्ताक्षरित int n = 1; n <= N; n++) { const अहस्ताक्षरित int n_squared = n * n; रिट += n_वर्ग; } वापसी रिट;
} </वाक्यविन्यास हाइलाइट>
ब्लॉक स्कोप के उपयोग का एक प्रतिनिधि उदाहरण यहां दिखाया गया सी कोड है, जहां दो चर लूप के दायरे में हैं: लूप वेरिएबल n, जिसे एक बार इनिशियलाइज़ किया जाता है और लूप के प्रत्येक पुनरावृत्ति पर बढ़ाया जाता है, और सहायक चर n_squared, जो प्रत्येक पुनरावृत्ति पर आरंभीकृत होता है। उद्देश्य फ़ंक्शन स्कोप में चर जोड़ने से बचना है जो केवल एक विशेष ब्लॉक के लिए प्रासंगिक हैं - उदाहरण के लिए, यह उन त्रुटियों को रोकता है जहां सामान्य लूप चर i को गलती से पहले से ही किसी अन्य मान पर सेट कर दिया गया है। इस उदाहरण में अभिव्यक्ति n * n
आम तौर पर एक सहायक चर को नहीं सौंपा जाएगा, और लूप का शरीर बस लिखा जाएगा ret += n * n
लेकिन अधिक जटिल उदाहरणों में सहायक चर उपयोगी होते हैं।
ब्लॉक मुख्य रूप से नियंत्रण प्रवाह के लिए उपयोग किए जाते हैं, जैसे कि अगर, जबकि, पाश के लिए के लिए, और इन मामलों में ब्लॉक स्कोप का मतलब है कि चर का दायरा किसी फ़ंक्शन के निष्पादन के प्रवाह की संरचना पर निर्भर करता है। हालाँकि, ब्लॉक स्कोप वाली भाषाएँ आमतौर पर नग्न ब्लॉकों के उपयोग की अनुमति देती हैं, जिनका एकमात्र उद्देश्य चर दायरे के ठीक-ठाक नियंत्रण की अनुमति देना है। उदाहरण के लिए, एक सहायक चर को एक ब्लॉक में परिभाषित किया जा सकता है, फिर उपयोग किया जाता है (जैसे, फ़ंक्शन स्कोप के साथ एक चर में जोड़ा जाता है) और ब्लॉक समाप्त होने पर छोड़ दिया जाता है, या थोड़ी देर के लूप को एक ब्लॉक में संलग्न किया जा सकता है जो लूप के अंदर उपयोग किए जाने वाले चर को आरंभ करता है। जिसे केवल एक बार प्रारंभ किया जाना चाहिए।
कई प्रोग्रामिंग भाषाओं की एक सूक्ष्मता, जैसे अल्गोल 68 और सी (इस उदाहरण में प्रदर्शित और सी 99 के बाद से मानकीकृत), यह है कि ब्लॉक-स्कोप चर न केवल ब्लॉक के शरीर के भीतर, बल्कि नियंत्रण कथन के भीतर भी घोषित किए जा सकते हैं, यदि कोई भी। यह फ़ंक्शन पैरामीटर के अनुरूप है, जो फ़ंक्शन डिक्लेरेशन (फ़ंक्शन बॉडी के ब्लॉक शुरू होने से पहले) में घोषित किया गया है, और पूरे फ़ंक्शन बॉडी के दायरे में है। यह मुख्य रूप से लूप के लिए उपयोग किया जाता है, जिसमें लूप की स्थिति से अलग एक इनिशियलाइज़ेशन स्टेटमेंट होता है, जबकि लूप के विपरीत, और यह एक सामान्य मुहावरा है।
छायांकन के लिए ब्लॉक स्कोप का उपयोग किया जा सकता है। इस उदाहरण में, ब्लॉक के अंदर ऑक्ज़ीलरी वेरिएबल को n भी कहा जा सकता था, जो पैरामीटर नाम को शैडो करता है, लेकिन त्रुटियों की संभावना के कारण इसे खराब स्टाइल माना जाता है। इसके अलावा, सी के कुछ वंशज, जैसे कि जावा और सी #, ब्लॉक स्कोप के लिए समर्थन होने के बावजूद (जिसमें एक स्थानीय चर को फ़ंक्शन के अंत से पहले संदर्भ से बाहर जाने के लिए बनाया जा सकता है), एक स्थानीय चर को दूसरे को छिपाने की अनुमति न दें . ऐसी भाषाओं में, दूसरे n की घोषणा के प्रयास के परिणामस्वरूप सिंटैक्स त्रुटि होगी, और n चरों में से एक का नाम बदलना होगा।
यदि किसी ब्लॉक का उपयोग किसी चर के मान को सेट करने के लिए किया जाता है, तो ब्लॉक स्कोप के लिए आवश्यक है कि वेरिएबल को ब्लॉक के बाहर घोषित किया जाए। यह एकल असाइनमेंट के साथ सशर्त बयानों के उपयोग को जटिल बनाता है। उदाहरण के लिए, पायथन में, जो ब्लॉक स्कोप का उपयोग नहीं करता है, एक वैरिएबल को इस तरह से इनिशियलाइज़ कर सकता है: <वाक्यविन्यास लैंग = अजगर> अगर सी:
ए = फू
अन्य:
एक =
</वाक्यविन्यास हाइलाइट>
कहाँ a
के बाद पहुँचा जा सकता है if
कथन।
पर्ल में, जिसमें ब्लॉक स्कोप है, इसके बजाय ब्लॉक से पहले वेरिएबल घोषित करने की आवश्यकता है: <वाक्यविन्यास प्रकाश लैंग = पर्ल> मेरा $ ए; अगर (सी) {
$ ए = 'फू';
} अन्य {
$ एक =;
} </वाक्यविन्यास हाइलाइट> इसके बजाय अक्सर इसे एकाधिक असाइनमेंट का उपयोग करके फिर से लिखा जाता है, चर को डिफ़ॉल्ट मान पर प्रारंभ किया जाता है। पायथन में (जहां यह आवश्यक नहीं है) यह होगा: <वाक्यविन्यास लैंग = अजगर> एक = अगर सी:
ए = फू
</वाक्यविन्यास हाइलाइट> जबकि पर्ल में यह होगा: <वाक्यविन्यास प्रकाश लैंग = पर्ल> मेरा $ ए =; अगर (सी) {
$ ए = 'फू';
} </वाक्यविन्यास हाइलाइट> एकल चर असाइनमेंट के मामले में, एक विकल्प एक ब्लॉक से बचने के लिए टर्नरी ऑपरेटर का उपयोग करना है, लेकिन यह सामान्य रूप से कई चर असाइनमेंट के लिए संभव नहीं है, और जटिल तर्क के लिए पढ़ना मुश्किल है।
यह C में एक अधिक महत्वपूर्ण मुद्दा है, विशेष रूप से स्ट्रिंग असाइनमेंट के लिए, क्योंकि स्ट्रिंग इनिशियलाइज़ेशन स्वचालित रूप से मेमोरी आवंटित कर सकता है, जबकि स्ट्रिंग असाइनमेंट को पहले से ही आरंभिक चर के लिए मेमोरी आवंटित करने, एक स्ट्रिंग कॉपी और जाँचने की आवश्यकता होती है कि ये सफल हैं।
<वाक्यविन्यास लैंग = पर्ल स्टाइल = फ्लोट: राइट; मार्जिन-लेफ्ट: 1em> {
मेरा $ काउंटर = 0; सब इंक्रीमेंट काउंटर { वापसी ++$ काउंटर; }
} </वाक्यविन्यास हाइलाइट>
कुछ भाषाएं ब्लॉक स्कोप की अवधारणा को एक फ़ंक्शन के बाहर अलग-अलग विस्तारों तक लागू करने की अनुमति देती हैं। उदाहरण के लिए, पर्ल स्निपेट में दाईं ओर, $counter
ब्लॉक स्कोप के साथ एक चर नाम है (के उपयोग के कारण my
कीवर्ड), जबकि increment_counter
वैश्विक दायरे वाला एक फ़ंक्शन नाम है। प्रत्येक कॉल करने के लिए increment_counter
के मान में वृद्धि करेगा $counter
एक के बाद एक, और नया मान वापस करें। इस ब्लॉक के बाहर का कोड कॉल कर सकता है increment_counter
, लेकिन अन्यथा का मान प्राप्त या परिवर्तित नहीं कर सकता $counter
. यह मुहावरा पर्ल में क्लोजर को परिभाषित करने की अनुमति देता है।
कार्य क्षेत्र
जब किसी फ़ंक्शन के भीतर घोषित चर का दायरा उस फ़ंक्शन से आगे नहीं बढ़ता है, तो इसे फ़ंक्शन स्कोप के रूप में जाना जाता है।[7] फ़ंक्शन स्कोप अधिकांश प्रोग्रामिंग भाषाओं में उपलब्ध है जो फ़ंक्शन या सबरूटीन में एक स्थानीय चर बनाने का एक तरीका प्रदान करते हैं: एक चर जिसका दायरा समाप्त होता है (जो संदर्भ से बाहर हो जाता है) जब फ़ंक्शन वापस आता है। ज्यादातर मामलों में चर का जीवनकाल फ़ंक्शन कॉल की अवधि है - यह एक स्वचालित चर है, जब फ़ंक्शन शुरू होता है (या चर घोषित किया जाता है), फ़ंक्शन के वापस आने पर नष्ट हो जाता है - जबकि चर का दायरा अंदर होता है कार्य, हालांकि भीतर का अर्थ इस बात पर निर्भर करता है कि दायरा शाब्दिक या गतिशील है या नहीं। हालाँकि, कुछ भाषाएँ, जैसे C, स्थैतिक स्थानीय चर भी प्रदान करती हैं, जहाँ चर का जीवनकाल कार्यक्रम का संपूर्ण जीवनकाल होता है, लेकिन चर केवल संदर्भ में होता है जब फ़ंक्शन के अंदर होता है। स्थैतिक स्थानीय चर के मामले में, चर तब बनाया जाता है जब कार्यक्रम आरंभ होता है, और केवल तभी नष्ट हो जाता है जब कार्यक्रम समाप्त हो जाता है, जैसा कि एक स्थिर वैश्विक चर के साथ होता है, लेकिन केवल एक स्वचालित स्थानीय चर की तरह एक फ़ंक्शन के संदर्भ में होता है।
महत्वपूर्ण रूप से, लेक्सिकल स्कोप में फंक्शन स्कोप के साथ एक वेरिएबल का स्कोप केवल फंक्शन के लेक्सिकल संदर्भ में होता है: यह संदर्भ से बाहर हो जाता है जब फ़ंक्शन के भीतर किसी अन्य फ़ंक्शन को कॉल किया जाता है, और फ़ंक्शन के वापस आने पर संदर्भ में वापस आ जाता है - जिसे फ़ंक्शन कहा जाता है कोई पहुंच नहीं है कॉलिंग फ़ंक्शंस के स्थानीय चर के लिए, और स्थानीय चर केवल उस फ़ंक्शन के शरीर के संदर्भ में होते हैं जिसमें उन्हें घोषित किया जाता है। इसके विपरीत, डायनेमिक स्कोप में, स्कोप फ़ंक्शन के निष्पादन संदर्भ तक विस्तारित होता है: स्थानीय चर तब संदर्भ में रहते हैं जब किसी अन्य फ़ंक्शन को कॉल किया जाता है, केवल संदर्भ से बाहर जाना जब परिभाषित फ़ंक्शन समाप्त होता है, और इस प्रकार स्थानीय चर फ़ंक्शन के संदर्भ में होते हैं। जिसमें उन्हें परिभाषित किया गया है और सभी को फंक्शन कहा जाता है। लेक्सिकल स्कोप और नेस्टेड फ़ंक्शंस वाली भाषाओं में, नेस्टेड फ़ंक्शंस के लिए स्थानीय चर संदर्भ में हैं, क्योंकि ये समान लेक्सिकल संदर्भ में हैं, लेकिन अन्य फ़ंक्शंस के लिए नहीं हैं जो लेक्सिकल रूप से नेस्टेड नहीं हैं। एक संलग्न फ़ंक्शन के स्थानीय चर को नेस्टेड समारोह के लिए गैर-स्थानीय चर के रूप में जाना जाता है। फ़ंक्शन का दायरा अनाम फ़ंक्शंस पर भी लागू होता है।
<वाक्यविन्यास प्रकाश लैंग = अजगर शैली = फ्लोट: दाएं; मार्जिन-बाएं: 1em> डेफ स्क्वायर (एन):
वापसी एन * एन
def योग_of_squares (एन):
कुल = 0 मैं = 0 जबकि मैं <= एन: कुल + = वर्ग (मैं) मैं + = 1 कुल वापसी
</वाक्यविन्यास हाइलाइट>
उदाहरण के लिए, दाईं ओर पायथन कोड के स्निपेट में, दो कार्यों को परिभाषित किया गया है: 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 चर पूरी तरह से अलग और असंबंधित हैं, एक ही नाम होने के बावजूद, क्योंकि वे फ़ंक्शन स्कोप के साथ लेक्सिकली स्कोप्ड लोकल वैरिएबल हैं: प्रत्येक का स्कोप अपना, लेक्सिकली अलग फंक्शन है और इस प्रकार, वे नहीं करते हैं टी ओवरलैप। इसलिए, sum_of_squares
कॉल कर सकते हैं square
अपने स्वयं के n को बदले बिना। इसी प्रकार, sum_of_squares
total और i नाम के वेरिएबल्स हैं; ये वेरिएबल्स, उनके सीमित दायरे के कारण, total या i नाम के किसी भी वेरिएबल्स के साथ हस्तक्षेप नहीं करेंगे जो किसी अन्य फ़ंक्शन से संबंधित हो सकते हैं। दूसरे शब्दों में, इन नामों और किसी भी असंबंधित नामों के बीच टकराव का कोई जोखिम नहीं है, भले ही वे समान हों।
कोई नाम मास्किंग नहीं हो रहा है: n नाम का केवल एक चर किसी भी समय संदर्भ में है, क्योंकि स्कोप ओवरलैप नहीं होते हैं। इसके विपरीत, डायनेमिक स्कोप वाली भाषा में एक समान टुकड़ा लिखा जाना था, कॉलिंग फ़ंक्शन में n तथाकथित फ़ंक्शन में संदर्भ में रहेगा - स्कोप ओवरलैप होगा - और नकाबपोश (छाया हुआ) होगा ) कॉल किए गए फ़ंक्शन में नए n द्वारा।
फ़ंक्शन स्कोप काफी अधिक जटिल है यदि फ़ंक्शंस प्रथम श्रेणी की वस्तुएं हैं और स्थानीय रूप से किसी फ़ंक्शन में बनाई जा सकती हैं और फिर वापस आ सकती हैं। इस मामले में नेस्टेड फ़ंक्शन में कोई भी चर जो इसके लिए स्थानीय नहीं हैं (फ़ंक्शन परिभाषा में अनबाउंड चर, जो एक संलग्न संदर्भ में चर के लिए हल होते हैं) एक क्लोजर (कंप्यूटर साइंस) बनाते हैं, न केवल फ़ंक्शन के रूप में, बल्कि इसके संदर्भ (चरों का) वापस किया जाना चाहिए, और फिर संभावित रूप से एक अलग संदर्भ में बुलाया जाना चाहिए। इसके लिए संकलक से काफी अधिक समर्थन की आवश्यकता होती है, और यह प्रोग्राम विश्लेषण को जटिल बना सकता है।
फ़ाइल का दायरा
नेम बाइंडिंग का स्कोप एक फाइल है, जिसे फाइल स्कोप के रूप में जाना जाता है। फ़ाइल का दायरा काफी हद तक सी (और सी ++) के लिए विशेष है, जहां फ़ाइल के शीर्ष स्तर पर घोषित चर और कार्यों का दायरा (किसी भी फ़ंक्शन के भीतर नहीं) पूरी फ़ाइल के लिए है - या सी के लिए, घोषणा से अंत तक स्रोत फ़ाइल, या अधिक सटीक रूप से अनुवाद इकाई (प्रोग्रामिंग) (आंतरिक लिंकिंग)। इसे मॉड्यूल स्कोप के रूप में देखा जा सकता है, जहां मॉड्यूल को फाइलों के साथ पहचाना जाता है, और अधिक आधुनिक भाषाओं में एक स्पष्ट मॉड्यूल स्कोप द्वारा प्रतिस्थापित किया जाता है। इनक्लूड स्टेटमेंट्स की उपस्थिति के कारण, जो आंतरिक संदर्भ में वेरिएबल्स और फ़ंक्शंस जोड़ते हैं और स्वयं को आगे शामिल स्टेटमेंट्स कह सकते हैं, यह निर्धारित करना मुश्किल हो सकता है कि फ़ाइल के मुख्य भाग में संदर्भ में क्या है।
उपरोक्त सी कोड स्निपेट में, फ़ंक्शन का नाम sum_of_squares
फ़ाइल का दायरा है।
मॉड्यूल गुंजाइश
नाम बंधन का दायरा एक मॉड्यूल है, जिसे मॉड्यूल स्कोप के रूप में जाना जाता है। मॉड्यूल स्कोप मॉड्यूलर प्रोग्रामिंग में उपलब्ध है जहां मॉड्यूल (जो विभिन्न फाइलों को फैला सकते हैं) एक जटिल प्रोग्राम की मूल इकाई हैं, क्योंकि वे जानकारी को छिपाने और एक सीमित इंटरफ़ेस को उजागर करने की अनुमति देते हैं। मॉड्यूल स्कोप भाषाओं के मापांक परिवार में अग्रणी था, और पायथन (जो मोडुला से प्रभावित था) एक प्रतिनिधि समकालीन उदाहरण है।
कुछ वस्तु-उन्मुख प्रोग्रामिंग भाषाओं में, जिनमें मॉड्यूल के लिए प्रत्यक्ष समर्थन की कमी होती है, जैसे कि सी ++, एक समान संरचना वर्ग पदानुक्रम द्वारा प्रदान की जाती है, जहां कक्षाएं कार्यक्रम की मूल इकाई होती हैं, और कक्षा में निजी विधियां हो सकती हैं। यह नाम संकल्प और कार्यक्षेत्र के बजाय गतिशील प्रेषण के संदर्भ में ठीक से समझा जाता है, हालांकि वे अक्सर समान भूमिका निभाते हैं। कुछ मामलों में ये दोनों सुविधाएं उपलब्ध हैं, जैसे कि पायथन में, जिसमें मॉड्यूल और कक्षाएं दोनों हैं, और कोड संगठन (मॉड्यूल-स्तरीय फ़ंक्शन या पारंपरिक रूप से निजी पद्धति के रूप में) प्रोग्रामर की पसंद है।
वैश्विक दायरा
एक नाम बंधन का दायरा एक संपूर्ण कार्यक्रम है, जिसे वैश्विक दायरे के रूप में जाना जाता है। ग्लोबल स्कोप वाले वेरिएबल नाम- जिन्हें सार्वत्रिक चर कहा जाता है- को अक्सर बुरा व्यवहार माना जाता है, कम से कम कुछ भाषाओं में, नाम टकराव की संभावना और अनजाने में मास्किंग के साथ-साथ खराब मॉड्युलैरिटी, और फंक्शन स्कोप या ब्लॉक स्कोप पर विचार किया जाता है। बेहतर। हालाँकि, ग्लोबल स्कोप का उपयोग आमतौर पर (भाषा के आधार पर) विभिन्न प्रकार के नामों के लिए किया जाता है, जैसे कि फ़ंक्शंस के नाम, क्लास के नाम (कंप्यूटर प्रोग्रामिंग) और अन्य डेटा प्रकारों के नाम। इन मामलों में टकराव से बचने के लिए तंत्र जैसे नाम स्थान का उपयोग किया जाता है।
लेक्सिकल स्कोप बनाम डायनेमिक स्कोप
स्थानीय चर का उपयोग - सीमित दायरे वाले चर नामों का, जो केवल एक विशिष्ट कार्य के भीतर मौजूद हैं - दो समान नाम वाले चर के बीच नाम टकराव के जोखिम से बचने में मदद करता है। हालाँकि, इस प्रश्न का उत्तर देने के लिए दो अलग-अलग दृष्टिकोण हैं: किसी फ़ंक्शन के भीतर होने का क्या अर्थ है?
लेक्सिकल स्कोप (या लेक्सिकल स्कोपिंग; जिसे स्टैटिक स्कोप या स्टैटिक स्कोपिंग भी कहा जाता है) में, यदि एक वैरिएबल नाम का स्कोप एक निश्चित फंक्शन है, तो इसका स्कोप फंक्शन डेफिनिशन का प्रोग्राम टेक्स्ट है: उस टेक्स्ट के भीतर, वेरिएबल नाम मौजूद है, और है चर के मान के लिए बाध्य है, लेकिन उस पाठ के बाहर, चर नाम मौजूद नहीं है। इसके विपरीत, डायनेमिक स्कोप (या डायनेमिक स्कोपिंग) में, यदि एक चर नाम का दायरा एक निश्चित कार्य है, तो इसका दायरा वह समय-अवधि है, जिसके दौरान कार्य निष्पादित हो रहा है: जब कार्य चल रहा हो, चर नाम मौजूद है, और है इसके मूल्य के लिए बाध्य है, लेकिन फ़ंक्शन के वापस आने के बाद, चर नाम मौजूद नहीं है। इसका मतलब है कि अगर कार्य करता है f
एक अलग परिभाषित फ़ंक्शन का आह्वान करता है g
, फिर लेक्सिकल स्कोप के तहत, function g
की पहुँच नहीं है f
के स्थानीय चर (का पाठ मानते हुए g
के पाठ के अंदर नहीं है f
), जबकि गतिशील दायरे में, function g
की पहुंच है f
के स्थानीय चर (के बाद से g
के आह्वान के दौरान आह्वान किया जाता है f
).
<वाक्यविन्यास लैंग = कंसोल शैली = फ्लोट: दाएं; मार्जिन-बाएं: 1em> $ # बैश भाषा $ एक्स = 1 $ फ़ंक्शन जी () {गूंज $ x; एक्स = 2; } $ फ़ंक्शन एफ () {स्थानीय एक्स = 3; जी ; } $ f # क्या यह 1 या 3 प्रिंट करता है? 3 $echo $x # क्या यह 1 या 2 प्रिंट करता है? 1 </वाक्यविन्यास हाइलाइट>
उदाहरण के लिए, दाईं ओर के कार्यक्रम पर विचार करें। पहली पंक्ति, x=1
, एक वैश्विक चर बनाता है x
और इसे इनिशियलाइज़ करता है 1
. दूसरी पंक्ति, function g() {echo $x ; एक्स = 2; }
, एक फ़ंक्शन को परिभाषित करता है g
जो वर्तमान मूल्य को प्रिंट करता है (गूंजता है)। x
, और फिर सेट करता है x
को 2
(पिछले मान को ओवरराइट करना)। तीसरी पंक्ति, function f() { local x=3 ; जी ; }
एक फ़ंक्शन को परिभाषित करता है f
जो एक स्थानीय चर बनाता है x
(समान रूप से नामित वैश्विक चर को छिपाते हुए) और इसे इनिशियलाइज़ करता है 3
, और फिर कॉल करता है g
. चौथी लाइन, f
, कॉल करती है f
. पांचवीं पंक्ति, echo $x
, के वर्तमान मान को प्रिंट करती है x
.
तो, यह प्रोग्राम वास्तव में क्या प्रिंट करता है? यह दायरे के नियमों पर निर्भर करता है। यदि इस प्रोग्राम की भाषा एक है जो लेक्सिकल स्कोप का उपयोग करती है, तो g
वैश्विक चर को प्रिंट और संशोधित करता है x
(क्योंकि g
बाहर परिभाषित किया गया है f
), इसलिए प्रोग्राम प्रिंट करता है 1
और तब 2
. इसके विपरीत, यदि यह भाषा गतिशील दायरे का उपयोग करती है, तब g
प्रिंट और संशोधित करता है f
का स्थानीय चर x
(क्योंकि g
भीतर से कहा जाता है f
), इसलिए प्रोग्राम प्रिंट करता है 3
और तब 1
. (जैसा कि होता है, प्रोग्राम की भाषा बैश (यूनिक्स शेल) है, जो डायनेमिक स्कोप का उपयोग करती है; इसलिए प्रोग्राम प्रिंट करता है 3
और तब 1
. यदि एक ही कोड के शेल के साथ चलाया जाता है जो लेक्सिकल स्कोप का उपयोग करता है, तो परिणाम अलग होंगे।)
लेक्सिकल स्कोप
लेक्सिकल स्कोप के साथ, एक नाम हमेशा इसके लेक्सिकल संदर्भ को संदर्भित करता है। यह प्रोग्राम टेक्स्ट की एक संपत्ति है और इसे भाषा कार्यान्वयन द्वारा रनटाइम कॉल स्टैक से स्वतंत्र बनाया गया है। क्योंकि इस मैचिंग के लिए केवल स्टैटिक प्रोग्राम टेक्स्ट के विश्लेषण की आवश्यकता होती है, इस प्रकार के स्कोप को स्टैटिक स्कोप भी कहा जाता है। लेक्सिकल स्कोप सभी ALGOL- आधारित भाषाओं जैसे पास्कल (प्रोग्रामिंग लैंग्वेज), मोडुला -2 और एडा (प्रोग्रामिंग लैंग्वेज) के साथ-साथ एमएल (प्रोग्रामिंग भाषा) और हास्केल (प्रोग्रामिंग भाषा) जैसी आधुनिक कार्यात्मक भाषाओं में मानक है। इसका उपयोग C (प्रोग्रामिंग लैंग्वेज) और इसके सिंटैक्टिक और सिमेंटिक रिलेटिव्स में भी किया जाता है, हालांकि विभिन्न प्रकार की सीमाओं के साथ। स्टैटिक स्कोप प्रोग्रामर को साधारण नाम प्रतिस्थापन के रूप में पैरामीटर, चर, स्थिरांक, प्रकार, फ़ंक्शन आदि जैसे ऑब्जेक्ट संदर्भों के बारे में तर्क करने की अनुमति देता है। इससे मॉड्यूलर कोड बनाना और इसके बारे में तर्क करना बहुत आसान हो जाता है, क्योंकि स्थानीय नामकरण संरचना को अलगाव में समझा जा सकता है। इसके विपरीत, डायनेमिक स्कोप प्रोग्रामर को सभी संभावित निष्पादन संदर्भों का अनुमान लगाने के लिए मजबूर करता है जिसमें मॉड्यूल का कोड लागू किया जा सकता है।
<वाक्यविन्यास लैंग = पास्कल शैली = फ्लोट: दाएं; मार्जिन-बाएं: 1em> कार्यक्रम ए; वर मैं: पूर्णांक;
कश्मीर: चार;
प्रक्रिया बी; वर कश्मीर: असली; एल: पूर्णांक;
प्रक्रिया सी; वर एम: असली; शुरू (*स्कोप ए+बी+सी*) अंत;
(*स्कोप ए+बी*) अंत;
(*स्कोप ए*)
अंत। </वाक्यविन्यास हाइलाइट>
उदाहरण के लिए, पास्कल लेक्सिकली स्कॉप्ड है। पास्कल प्रोग्राम फ़्रैगमेंट को दाईं ओर देखें। चर I
सभी बिंदुओं पर दिखाई देता है, क्योंकि यह उसी नाम के किसी अन्य चर से कभी नहीं छिपा होता है। char
ई> चर K
केवल मुख्य कार्यक्रम में दिखाई देता है क्योंकि यह द्वारा छिपा हुआ है real
चर K
प्रक्रिया में दृष्टिगोचर होता है B
और C
केवल। चर L
प्रक्रिया में भी दिखाई देता है B
और C
लेकिन यह किसी अन्य चर को नहीं छिपाता है। चर M
प्रक्रिया में ही दिखाई देता है C
और इसलिए प्रक्रिया से भी पहुंच योग्य नहीं है B
या मुख्य कार्यक्रम। साथ ही, प्रक्रिया C
प्रक्रिया में ही दिखाई देता है B
और इसलिए मुख्य कार्यक्रम से नहीं बुलाया जा सकता।
एक और प्रक्रिया हो सकती थी C
प्रक्रिया के बाहर कार्यक्रम में घोषित किया गया B
. कार्यक्रम में वह स्थान जहांC
उल्लेख किया गया है तो यह निर्धारित करता है कि नामित दो प्रक्रियाओं में से कौन सी है C
यह प्रतिनिधित्व करता है, इस प्रकार वेरिएबल्स के दायरे के साथ सटीक रूप से अनुरूप है।
प्रथम श्रेणी के फ़ंक्शन के साथ भाषाओं में लेक्सिकल स्कोप का सही कार्यान्वयन | प्रथम श्रेणी के नेस्टेड फ़ंक्शंस तुच्छ नहीं हैं, क्योंकि इसके लिए प्रत्येक फ़ंक्शन मान को अपने साथ ले जाने के लिए चर के मानों का रिकॉर्ड रखना पड़ता है, जिस पर यह निर्भर करता है (फ़ंक्शन की जोड़ी) और इस संदर्भ को क्लोजर (कंप्यूटर विज्ञान) कहा जाता है)। कार्यान्वयन और कंप्यूटर आर्किटेक्चर के आधार पर, वेरिएबल ऊपर देखो थोड़ा अक्षम हो सकता है[citation needed] जब बहुत गहराई से शाब्दिक रूप से नेस्टिंग (कंप्यूटिंग) कार्यों का उपयोग किया जाता है, हालांकि इसे कम करने के लिए प्रसिद्ध तकनीकें हैं।[8][9] साथ ही, नेस्टेड फ़ंक्शंस के लिए जो केवल अपने स्वयं के तर्कों और (तत्काल) स्थानीय चरों को संदर्भित करते हैं, सभी सापेक्ष स्थानों को संकलन समय पर जाना जा सकता है। इस प्रकार के नेस्टेड फ़ंक्शन का उपयोग करते समय कोई ओवरहेड नहीं होता है। यह प्रोग्राम के विशेष भागों पर लागू होता है जहां नेस्टेड फ़ंक्शंस का उपयोग नहीं किया जाता है, और स्वाभाविक रूप से, ऐसी भाषा में लिखे प्रोग्रामों के लिए जहां नेस्टेड फ़ंक्शंस उपलब्ध नहीं हैं (जैसे सी भाषा में)।
इतिहास
लेक्सिकल स्कोप का पहली बार 1960 के दशक में अनिवार्य भाषा ALGOL 60 के लिए उपयोग किया गया था और तब से अधिकांश अन्य अनिवार्य भाषाओं में इसे चुना गया है।[4] पास्कल (प्रोग्रामिंग लैंग्वेज) और सी (प्रोग्रामिंग लैंग्वेज) जैसी भाषाओं में हमेशा लेक्सिकल स्कोप होता है, क्योंकि वे दोनों उन विचारों से प्रभावित होते हैं जो ALGOL 60 और ALGOL 68 में गए थे (हालाँकि C में लेक्सिकल नेस्टेड फ़ंक्शंस शामिल नहीं थे)।
पर्ल डायनेमिक स्कोप वाली एक भाषा है जिसने बाद में स्टैटिक स्कोप जोड़ा।
मूल लिस्प (प्रोग्रामिंग लैंग्वेज) दुभाषिया (1960) ने डायनेमिक स्कोप का इस्तेमाल किया। डीप बाइंडिंग, जो स्टैटिक (लेक्सिकल) स्कोप का अनुमान लगाती है, को 1962 के आसपास LISP 1.5 में पेश किया गया था (जॉन मैक्कार्थी (कंप्यूटर वैज्ञानिक) के तहत काम कर रहे स्टीव रसेल (कंप्यूटर वैज्ञानिक) द्वारा विकसित फनार्ग डिवाइस के माध्यम से)।
सभी प्रारंभिक लिस्प (प्रोग्रामिंग भाषा) दुभाषियों पर आधारित होने पर गतिशील दायरे का उपयोग करते थे। 1982 में, गाइ एल. स्टील जूनियर और कॉमन एलआईएसपी ग्रुप ने कॉमन एलआईएसपी का अवलोकन प्रकाशित किया,[10] इतिहास की एक संक्षिप्त समीक्षा और उस क्षण तक लिस्प के अलग-अलग कार्यान्वयन और उन विशेषताओं की समीक्षा जो एक सामान्य लिस्प कार्यान्वयन में होनी चाहिए। पेज 102 पर, हम पढ़ते हैं:
अधिकांश LISP कार्यान्वयन आंतरिक रूप से असंगत होते हैं जिसमें डिफ़ॉल्ट रूप से दुभाषिया और संकलक प्रोग्राम को सही करने के लिए अलग-अलग शब्दार्थ निर्दिष्ट कर सकते हैं; यह मुख्य रूप से इस तथ्य से उपजा है कि दुभाषिया सभी चरों को गतिशील रूप से दायरे में रखता है, जबकि संकलक सभी चरों को स्थानीय मानता है जब तक कि अन्यथा मानने के लिए मजबूर न किया जाए। यह सुविधा और दक्षता के लिए किया गया है, लेकिन इससे बहुत सूक्ष्म बग हो सकते हैं। सामान्य एलआईएसपी की परिभाषा स्पष्ट रूप से दुभाषिया और संकलक को सही कार्यक्रमों पर समान शब्दार्थ लगाने की आवश्यकता के द्वारा ऐसी विसंगतियों से बचाती है।
इस प्रकार सामान्य लिस्प के कार्यान्वयन के लिए सामान्य लिस्प#लेक्सिकल होना आवश्यक था। दोबारा, सामान्य एलआईएसपी के एक सिंहावलोकन से:
इसके अलावा, कॉमन LISP निम्नलिखित सुविधाएं प्रदान करता है (जिनमें से अधिकांश MacLisp, InterLisp या Lisp Machines Lisp से उधार ली गई हैं): (...) पूरी तरह से लेक्सिकली स्कोप्ड वेरिएबल्स। तथाकथित FUNARG समस्या[11][12] नीचे और ऊपर दोनों मामलों में पूरी तरह से हल हो गया है।
उसी वर्ष जिसमें कॉमन एलआईएसपी का एक अवलोकन (1982) प्रकाशित हुआ था, एक संकलित, शाब्दिक दायरे वाले लिस्प, जिसे योजना प्रोग्रामिंग भाषा का इतिहास कहा जाता है, के प्रारंभिक डिजाइन (गाइ एल स्टील जूनियर द्वारा भी) प्रकाशित किए गए थे और संकलक कार्यान्वयन प्रयास किए जा रहे थे। उस समय, लिस्प में लेक्सिकल स्कोप को आमतौर पर लागू करने में अक्षम होने की आशंका थी। टी के इतिहास में,[13] ओलिन शिवर्स लिखते हैं:
उस समय उत्पादन में उपयोग किए जाने वाले सभी गंभीर लिस्प्स गतिशील रूप से दायरे में थे। ऐसा कोई नहीं जिसने खरगोश को ध्यान से न पढ़ा हो[14] थीसिस (1978 में गाइ लेविस स्टील जूनियर द्वारा लिखित) का मानना था कि लेक्सिकल स्कोप उड़ जाएगा; यहां तक कि जिन कुछ लोगों ने इसे पढ़ा था, वे भी विश्वास की एक छलांग ले रहे थे कि यह गंभीर उत्पादन उपयोग में काम करने वाला था।
लेक्सिकल स्कोप शब्द कम से कम 1967 तक है,[15] जबकि लेक्सिकल स्कूपिंग शब्द कम से कम 1970 तक है, जहां इसका उपयोग लिस्प बोली एमडीएल (प्रोग्रामिंग भाषा) (तब मडल के रूप में जाना जाता है) के दायरे के नियमों का वर्णन करने के लिए प्रोजेक्ट मैक में किया गया था।[16]
डायनेमिक स्कोप
गतिशील दायरे के साथ, एक नाम निष्पादन संदर्भ को संदर्भित करता है। तकनीकी शब्दों में, इसका अर्थ है कि प्रत्येक नाम में बाइंडिंग का वैश्विक ढेर (डेटा संरचना) है। नाम के साथ एक स्थानीय चर का परिचय x
वैश्विक पर एक बंधन को धकेलता है x
स्टैक (जो खाली हो सकता है), जो पॉप ऑफ हो जाता है जब नियंत्रण प्रवाह गुंजाइश छोड़ देता है। का मूल्यांकन x
किसी भी संदर्भ में हमेशा शीर्ष बंधन उत्पन्न होता है। ध्यान दें कि यह संकलन-समय पर नहीं किया जा सकता है क्योंकि बाइंडिंग स्टैक केवल रन टाइम (प्रोग्राम जीवनचक्र चरण) | रन-टाइम पर मौजूद होता है, यही कारण है कि इस प्रकार के दायरे को डायनेमिक स्कोप कहा जाता है।
आधुनिक भाषाओं में गतिशील दायरा असामान्य है।[4]
आम तौर पर, कुछ ब्लॉक (प्रोग्रामिंग) को बाइंडिंग बनाने के लिए परिभाषित किया जाता है जिसका जीवनकाल ब्लॉक का निष्पादन समय होता है; यह डायनेमिक स्कोप प्रक्रिया में स्टैटिक स्कोप की कुछ विशेषताओं को जोड़ता है। हालाँकि, चूंकि कोड के एक भाग को कई अलग-अलग स्थानों और स्थितियों से बुलाया जा सकता है, इसलिए शुरुआत में यह निर्धारित करना मुश्किल हो सकता है कि जब एक चर का उपयोग किया जाता है (या यदि कोई मौजूद है) तो कौन सी बाइंडिंग लागू होगी। यह फायदेमंद हो सकता है; कम से कम ज्ञान के सिद्धांत के अनुप्रयोग से पता चलता है कि कोड किसी चर के मान के कारणों (या परिस्थितियों) के आधार पर टालता है, लेकिन केवल चर की परिभाषा के अनुसार मूल्य का उपयोग करता है। साझा किए गए डेटा की यह संकीर्ण व्याख्या किसी फ़ंक्शन के व्यवहार को सिस्टम की वर्तमान स्थिति (या नीति) के अनुकूल बनाने के लिए एक बहुत ही लचीली प्रणाली प्रदान कर सकती है। हालांकि, यह लाभ इस तरह से उपयोग किए जाने वाले सभी चरों के सावधानीपूर्वक दस्तावेज़ीकरण के साथ-साथ एक चर के व्यवहार के बारे में धारणाओं से बचने पर निर्भर करता है, और किसी कार्यक्रम के विभिन्न भागों के बीच हस्तक्षेप का पता लगाने के लिए कोई तंत्र प्रदान नहीं करता है। कुछ भाषाएँ, जैसे पर्ल और सामान्य लिस्प, प्रोग्रामर को एक चर को परिभाषित या पुनर्परिभाषित करते समय स्थिर या गतिशील गुंजाइश चुनने की अनुमति देती हैं। डायनेमिक स्कोप का उपयोग करने वाली भाषाओं के उदाहरणों में लोगो (प्रोग्रामिंग भाषा), Emacs Lisp, LaTeX और शेल भाषाएँ Bash (Unix शेल), डेबियन अल्मक्विस्ट शेल और Windows PowerShell शामिल हैं।
डायनेमिक स्कोप को लागू करना काफी आसान है। किसी नाम का मान खोजने के लिए, प्रोग्राम रनटाइम स्टैक को पार कर सकता है, नाम के मान के लिए प्रत्येक सक्रियण रिकॉर्ड (प्रत्येक फ़ंक्शन का स्टैक फ़्रेम) की जाँच कर सकता है। व्यवहार में, इसे संघ सूची के उपयोग के माध्यम से और अधिक कुशल बनाया जाता है, जो नाम/मूल्य जोड़े का ढेर है। जब भी घोषणा की जाती है तो जोड़े को इस स्टैक पर धकेल दिया जाता है, और जब भी वेरिएबल संदर्भ से बाहर हो जाते हैं तो पॉप हो जाते हैं।[17] शालो बाइंडिंग एक वैकल्पिक रणनीति है जो काफी तेज है, एक केंद्रीय संदर्भ तालिका का उपयोग करती है, जो प्रत्येक नाम को अर्थों के ढेर के साथ जोड़ती है। यह एक विशेष नाम खोजने के लिए रन-टाइम के दौरान एक रैखिक खोज से बचा जाता है, लेकिन इस तालिका को ठीक से बनाए रखने के लिए सावधानी बरतनी चाहिए।[17] ध्यान दें कि ये दोनों रणनीतियाँ किसी एक चर के लिए बाइंडिंग के लिए अंतिम-इन-फर्स्ट-आउट (एलआईएफओ (कंप्यूटिंग)) का आदेश मानती हैं; व्यवहार में सभी बन्धन इसी क्रम में होते हैं।
सरल वैश्विक चर के साथ गतिशील चर का प्रतिनिधित्व एक और भी सरल कार्यान्वयन है। प्रोग्राम के लिए अदृश्य स्टैक पर अज्ञात स्थान में मूल मान को सहेजकर स्थानीय बाध्यकारी किया जाता है। जब वह बाध्यकारी दायरा समाप्त हो जाता है, तो मूल मान इस स्थान से पुनर्स्थापित किया जाता है। वास्तव में, डायनेमिक स्कोप की उत्पत्ति इसी तरीके से हुई। लिस्प के शुरुआती कार्यान्वयन ने स्थानीय चरों को लागू करने के लिए इस स्पष्ट रणनीति का इस्तेमाल किया, और यह अभ्यास कुछ बोलियों में जीवित है जो अभी भी उपयोग में हैं, जैसे कि GNU Emacs Lisp। लिस्प में बाद में लेक्सिकल स्कोप पेश किया गया था। यह उपरोक्त उथली बाध्यकारी योजना के बराबर है, सिवाय इसके कि केंद्रीय संदर्भ तालिका केवल वैश्विक चर बाध्यकारी संदर्भ है, जिसमें चर का वर्तमान अर्थ इसका वैश्विक मूल्य है। वैश्विक चर बनाए रखना जटिल नहीं है। उदाहरण के लिए, एक प्रतीक वस्तु के वैश्विक मूल्य के लिए एक समर्पित स्लॉट हो सकता है।
डायनेमिक स्कोप थ्रेड-लोकल स्टोरेज के लिए एक उत्कृष्ट अमूर्तता प्रदान करता है, लेकिन अगर इसका उपयोग इस तरह किया जाता है तो यह वैश्विक चर को बचाने और पुनर्स्थापित करने पर आधारित नहीं हो सकता है। प्रत्येक चर के लिए थ्रेड-स्थानीय कुंजी रखने के लिए एक संभावित कार्यान्वयन रणनीति है। जब चर का उपयोग किया जाता है, तो थ्रेड-स्थानीय कुंजी का उपयोग थ्रेड-लोकल मेमोरी लोकेशन तक पहुंचने के लिए किया जाता है (संकलक द्वारा उत्पन्न कोड द्वारा, जो जानता है कि कौन से चर गतिशील हैं और कौन से शाब्दिक हैं)। यदि कॉलिंग थ्रेड के लिए थ्रेड-लोकल कुंजी मौजूद नहीं है, तो वैश्विक स्थान का उपयोग किया जाता है। जब एक चर स्थानीय रूप से बाध्य होता है, तो पूर्व मान स्टैक पर छिपे हुए स्थान में संग्रहीत होता है। थ्रेड-लोकल स्टोरेज को वेरिएबल की की के तहत बनाया जाता है, और नया मान वहां स्टोर किया जाता है। उस थ्रेड के भीतर वेरिएबल के नेस्टेड ओवरराइड बस इस थ्रेड-लोकल लोकेशन को सेव और रिस्टोर करते हैं। जब प्रारंभिक, सबसे बाहरी ओवरराइड का संदर्भ समाप्त हो जाता है, तो थ्रेड-स्थानीय कुंजी को हटा दिया जाता है, चर के वैश्विक संस्करण को एक बार फिर उस थ्रेड पर उजागर किया जाता है।
संदर्भात्मक पारदर्शिता के साथ डायनामिक स्कोप केवल वर्तमान फ़ंक्शन के तर्क स्टैक तक ही सीमित है, और लेक्सिकल स्कोप के साथ मेल खाता है।
मैक्रो विस्तार
आधुनिक भाषाओं में, preprocessor में मैक्रो विस्तार वास्तविक गतिशील दायरे का एक प्रमुख उदाहरण है। मैक्रो भाषा ही नामों को हल किए बिना केवल स्रोत कोड को रूपांतरित करती है, लेकिन चूंकि विस्तार किया जाता है, जब विस्तारित पाठ में नाम तब हल किए जाते हैं (विशेष रूप से मुक्त चर), वे जहां वे विस्तारित होते हैं, उसके आधार पर हल किए जाते हैं (शिथिल रूप से) कहा जाता है), जैसे गतिशील दायरा हो रहा था।
मैक्रो विस्तार के लिए उपयोग किए जाने वाले सी प्रीप्रोसेसर में वास्तविक गतिशील गुंजाइश है, क्योंकि यह स्वयं नाम संकल्प नहीं करता है और यह स्वतंत्र है कि मैक्रो परिभाषित किया गया है। उदाहरण के लिए, मैक्रो: <वाक्यविन्यास प्रकाश लैंग = सी>
- ADD_A(x) x + a परिभाषित करें
</वाक्यविन्यास हाइलाइट>
जोड़ने के लिए विस्तारित होगा a
पास किए गए चर के लिए, इस नाम के साथ केवल बाद में कंपाइलर द्वारा हल किया गया जहां मैक्रो के आधार पर ADD_A
कहा जाता है (ठीक से, विस्तारित)। उचित रूप से, सी प्रीप्रोसेसर केवल लेक्सिकल विश्लेषण करता है, टोकेनाइजेशन चरण के दौरान मैक्रो का विस्तार करता है, लेकिन सिंटैक्स ट्री में पार्सिंग या नाम रिज़ॉल्यूशन नहीं करता है।
उदाहरण के लिए, निम्नलिखित कोड में, name a
मैक्रो में विस्तार स्थल पर स्थानीय चर के लिए (विस्तार के बाद) हल किया गया है:
<वाक्यविन्यास प्रकाश लैंग = सी>
- ADD_A(x) x + a परिभाषित करें
शून्य ऐड_ऑन (इंट * एक्स) {
कॉन्स्ट इंट ए = 1; *x = ADD_A(*x);
}
शून्य जोड़_दो (इंट * एक्स) {
कास्ट इंट ए = 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] जावास्क्रिप्ट ऑब्जेक्ट्स के गुणों का नाम संकल्प प्रोटोटाइप पेड़ में विरासत पर आधारित है- पेड़ में जड़ के पथ को प्रोटोटाइप श्रृंखला कहा जाता है- और चर और कार्यों के नाम संकल्प से अलग होता है।
लिस्प
लिस्प (प्रोग्रामिंग लैंग्वेज) बोलियों के दायरे के लिए विभिन्न नियम हैं।
मूल लिस्प ने गतिशील दायरे का इस्तेमाल किया; यह ALGOL से प्रेरित स्कीम (प्रोग्रामिंग लैंग्वेज) थी, जिसने लिस्प परिवार के लिए स्थिर (लेक्सिकल) गुंजाइश पेश की।
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