Computer >> कंप्यूटर >  >> प्रोग्रामिंग >> Ruby

रूबी में बाइंडिंग और लेक्सिकल स्कोप

नया साल मुबारक हो, और रूबी मैजिक में आपका स्वागत है! इस शीतकालीन एपिसोड में, हम बाइंडिंग और स्कोप में गोता लगाएँगे। तो अपनी स्की पहनो और हमारे पीछे जंगल में जाओ।

पिछली बार, हमने रूबी में ब्लॉक, प्रोसेस और लैम्ब्डा की तुलना करके क्लोजर को देखा था। तीन प्रकारों के बीच के अंतरों के अलावा, हमने क्लोजर . को परिभाषित करने वाली चीज़ों को छुआ है ।

<ब्लॉकक्वॉट>

एक बंद एक पर्यावरण के साथ एक प्रथम श्रेणी का कार्य है। पर्यावरण उन चरों का मानचित्रण है जो बंद होने के समय मौजूद थे। क्लोजर इन चरों तक अपनी पहुंच बनाए रखता है, भले ही वे किसी अन्य दायरे में परिभाषित हों।

हमने रूबी के समकक्ष प्रथम श्रेणी के कार्यों की खोज की है, लेकिन हमने आसानी से वातावरण को छोड़ दिया है . इस कड़ी में, रूबी लेक्सिकल स्कोप को कैसे हैंडल करती है, इसकी जांच करके हम यह देखेंगे कि यह वातावरण क्लोजर, क्लास और क्लास इंस्टेंस के लिए कैसे काम करता है। इसके बाइंडिंग . के माध्यम से ।

लेक्सिकल स्कोप

प्रोग्रामिंग में, स्कोप बाइंडिंग . को संदर्भित करता है कोड के एक विशिष्ट भाग पर उपलब्ध है। एक बाध्यकारी, या नाम बाध्यकारी , किसी नाम को स्मृति संदर्भ से बांधता है, जैसे किसी चर का नाम उसके मान से। कार्यक्षेत्र परिभाषित करता है कि self का अर्थ है, वे विधियाँ जिन्हें बुलाया जा सकता है, और वेरिएबल जो उपलब्ध हैं।

रूबी, अधिकांश आधुनिक प्रोग्रामिंग भाषाओं की तरह, एक स्थिर दायरे का उपयोग करती है, जिसे अक्सर लेक्सिकल स्कोप . कहा जाता है (गतिशील दायरे के विपरीत)। वर्तमान दायरा कोड की संरचना पर आधारित है और कोड के विशिष्ट भागों में उपलब्ध चर को निर्धारित करता है। इसका मतलब यह है कि जब कोड विधियों, ब्लॉक और कक्षाओं के बीच कूदता है तो दायरा बदल जाता है-क्योंकि उन सभी में अलग-अलग स्थानीय चर हो सकते हैं, उदाहरण के लिए।

def bar
  foo = 1
  foo
end
 
bar #  => 1

इस विधि में, हम एक स्थानीय चर बनाते हैं एक विधि के अंदर और इसे कंसोल पर प्रिंट करें। वेरिएबल दायरे में है विधि के अंदर, जैसा कि वहां बनाया गया है।

foo = 1
 
def bar
  foo
end
 
bar # => NameError (undefined local variable or method `foo' for main:Object)

इस उदाहरण में, हम वेरिएबल को मेथड के बाहर बनाते हैं। जब हम वेरिएबल को किसी मेथड के अंदर बुलाते हैं, तो हमें एक एरर मिलती है, क्योंकि वेरिएबल स्कोप से बाहर . है . स्थानीय चरों का दायरा बहुत सख्त होता है, जिसका अर्थ है कि एक विधि एक चर को अपने आप से बाहर तब तक एक्सेस नहीं कर सकती जब तक कि इसे एक तर्क के रूप में पारित नहीं किया जाता है।

@foo = 1
 
def bar
  @foo
end
 
bar #  => 1

जबकि स्थानीय चर स्थानीय रूप से उपलब्ध हैं, आवृत्ति चर क्लास इंस्टेंस के सभी तरीकों के लिए उपलब्ध हैं।

इनहेरिट किए गए स्कोप और प्रोक बाइंडिंग

जैसा कि हमने पिछले उदाहरणों में देखा है, स्कोप कोड में स्थान पर आधारित है। एक विधि के बाहर परिभाषित एक स्थानीय चर विधि के दायरे में नहीं है, लेकिन इसे एक आवृत्ति चर में बदलकर उपलब्ध कराया जा सकता है। विधियाँ उनके बाहर परिभाषित स्थानीय चरों तक नहीं पहुँच सकतीं क्योंकि विधियों का अपना दायरा होता है, उनकी अपनी बाइंडिंग के साथ।

प्रोसेस (ब्लॉक और लैम्ब्डा सहित, विस्तार से) अलग हैं। जब भी किसी खरीद को तत्काल किया जाता है, तो एक बाइंडिंग बनाई जाती है जो उस संदर्भ में स्थानीय चरों के संदर्भों को इनहेरिट करती है जिस संदर्भ में ब्लॉक बनाया गया था।

foo = 1
Proc.new { foo }.call # => 1

इस उदाहरण में, हमने foo . नाम का एक वेरिएबल सेट किया है करने के लिए 1 . आंतरिक रूप से, दूसरी पंक्ति पर बनाई गई प्रोक वस्तु एक नया बंधन बनाती है। प्रोक को कॉल करते समय, हम वेरिएबल का मान पूछ सकते हैं।

चूंकि खरीद शुरू होने पर बाइंडिंग बनाई जाती है, हम वैरिएबल को परिभाषित करने से पहले प्रो नहीं बना सकते हैं, भले ही वेरिएबल परिभाषित होने तक ब्लॉक को कॉल न किया जाए।

proc = Proc.new { foo }
foo = 1
proc.call # => NameError (undefined local variable or method `foo' for main:Object)

खरीद को कॉल करने से एक NameError उत्पन्न होगा चूंकि चर को proc की बाइंडिंग में परिभाषित नहीं किया गया है। इस प्रकार, किसी खरीद में एक्सेस किए गए किसी भी चर को खरीद के निर्माण या तर्क के रूप में पारित करने से पहले परिभाषित किया जाना चाहिए।

foo = 1
proc = Proc.new { foo }
foo = 2
proc.call # => 2

हालांकि, मुख्य संदर्भ में परिभाषित किए जाने के बाद हम चर को बदल सकते हैं क्योंकि proc की बाध्यकारी इसे कॉपी करने के बजाय इसका संदर्भ रखती है।

foo = 1
Proc.new { foo = 2 }.call
foo #=> 2

इस उदाहरण में, हम देख सकते हैं कि foo वेरिएबल उसी ऑब्जेक्ट को इंगित करता है जब proc में इसके बाहर के रूप में होता है। हम इसे खरीद के अंदर अपडेट कर सकते हैं ताकि इसके बाहर के वेरिएबल को भी अपडेट किया जा सके।

बाइंडिंग

मौजूदा दायरे पर नज़र रखने के लिए, रूबी बाइंडिंग . का उपयोग करती है , जो कोड में प्रत्येक स्थिति पर निष्पादन संदर्भ को समाहित करता है। binding विधि एक binding लौटाती है ऑब्जेक्ट जो वर्तमान स्थिति में बाइंडिंग का वर्णन करता है।

foo = 1
binding.local_variables # => [:foo]

बाइंडिंग ऑब्जेक्ट में #local_variables . नामक एक विधि होती है जो वर्तमान दायरे में उपलब्ध सभी स्थानीय चरों के नाम लौटाता है।

foo = 1
binding.eval("foo") # => 1

बाइंडिंग पर कोड का मूल्यांकन #eval . का उपयोग करके किया जा सकता है तरीका। ऊपर दिया गया उदाहरण बहुत उपयोगी नहीं है, जैसे कि केवल foo . को कॉल करना एक ही परिणाम होगा। हालांकि, चूंकि एक बंधन एक वस्तु है जिसे चारों ओर से पारित किया जा सकता है, इसका उपयोग कुछ और दिलचस्प चीजों के लिए किया जा सकता है। आइए एक उदाहरण देखें।

एक वास्तविक जीवन उदाहरण

अब जबकि हमने अपने गैरेज की सुरक्षा में बाइंडिंग के बारे में जान लिया है, जैसे उन्हें ढलानों पर ले जाना और बर्फ में खेलना। रूबी द्वारा पूरी भाषा में बाइंडिंग के आंतरिक उपयोग के अलावा, कुछ ऐसी स्थितियां भी हैं जहां बाध्यकारी वस्तुओं का स्पष्ट रूप से उपयोग किया जाता है। एक अच्छा उदाहरण है ERB—रूबी का टेंपलेटिंग सिस्टम।

require 'erb'
 
x = 1
 
def y
  2
end
 
template = ERB.new("x is <%= x %>, y() returns <%= y %>, self is `<%= self %>`")
template.result(binding) # => "x is 1, y() returns 2, self is `main`"

इस उदाहरण में, हम x . नाम का एक वेरिएबल बनाते हैं , y . नामक एक विधि , और एक ERB टेम्प्लेट जो दोनों को संदर्भित करता है। फिर हम वर्तमान बाइंडिंग को ERB#result . पर पास करते हैं , जो टेम्पलेट में ERB टैग का मूल्यांकन करता है और भरे हुए चर के साथ एक स्ट्रिंग देता है।

हुड के तहत, ERB Binding#eval . का उपयोग करता है पारित बाध्यकारी के दायरे में प्रत्येक ईआरबी टैग की सामग्री का मूल्यांकन करने के लिए। ऊपर दिए गए उदाहरण के लिए काम करने वाला एक सरलीकृत कार्यान्वयन इस तरह दिख सकता है:

class DiyErb
  def initialize(template)
    @template = template
  end
 
  def result(binding)
    @template.gsub(/<%=(.+?)%>/) do
      binding.eval($1)
    end
  end
end
 
x = 1
 
def y
  2
end
 
template = DiyErb.new("x is <%= x %>, y() returns <%= y %>, self is `<%= self %>`")
template.result(binding) # => "x is 1, y() returns 2, self is `main`"

DiyErb वर्ग आरंभीकरण पर एक टेम्पलेट स्ट्रिंग लेता है। इसका #result विधि सभी ईआरबी टैग ढूंढती है और उनकी सामग्री के मूल्यांकन के परिणाम के साथ उन्हें बदल देती है। ऐसा करने के लिए, यह Binding#eval . को कॉल करता है पारित बाध्यकारी पर, ईआरबी टैग की सामग्री के साथ।

#result . पर कॉल करते समय वर्तमान बाइंडिंग पास करके विधि, eval कॉल स्पष्ट रूप से पारित किए बिना, विधि के बाहर और यहां तक ​​​​कि कक्षा के बाहर परिभाषित चरों तक पहुंच सकते हैं।

क्या हमने आपको जंगल में खो दिया?

हमें उम्मीद है कि आपने जंगल में हमारी स्की यात्रा का आनंद लिया। हम उन पर प्रकाश डालने के बाद, स्कोप और क्लोजर में गहराई तक गए। हमें उम्मीद है कि हमने आपको जंगल में नहीं खोया है। कृपया हमें बताएं कि क्या आप बाइंडिंग के बारे में अधिक जानना चाहते हैं, या कोई अन्य रूबी विषय है जिसमें आप गोता लगाना चाहते हैं।

हमारा अनुसरण करने के लिए धन्यवाद और कृपया अगले डेवलपर के लिए उन्हें छोड़ने से पहले अपने बाइंडिंग से बर्फ़ हटा दें। यदि आप इन जादुई यात्राओं को पसंद करते हैं, तो आप एक ई-मेल प्राप्त करने के लिए रूबी मैजिक की सदस्यता लेना पसंद कर सकते हैं, जब हम महीने में एक बार एक नया लेख प्रकाशित करते हैं।


  1. जावा में चर का दायरा और जीवनकाल?

    इंस्टेंस वेरिएबल एक चर जो एक वर्ग के अंदर और सभी विधियों और ब्लॉकों के बाहर घोषित किया जाता है, एक आवृत्ति चर है। एक आवृत्ति चर का सामान्य दायरा स्थिर विधियों को छोड़कर पूरे वर्ग में होता है। एक आवृत्ति चर का जीवनकाल तब तक होता है जब तक कि वस्तु स्मृति में नहीं रहती। कक्षा चर एक वेरिएबल जो एक वर्ग

  1. रुबोकॉप के साथ लाइनिंग और ऑटो-फॉर्मेटिंग रूबी कोड

    लाइनिंग प्रोग्रामेटिक और शैलीगत त्रुटियों के लिए स्रोत कोड की स्वचालित जाँच है। यह जाँच एक स्थिर कोड विश्लेषण उपकरण द्वारा की जाती है जिसे लिंटर कहा जाता है। एक कोड फ़ॉर्मेटर, हालांकि, स्रोत कोड को स्वरूपित करने से संबंधित एक उपकरण है, ताकि यह नियमों के पूर्व-कॉन्फ़िगर किए गए सेट का सख्ती से पालन कर

  1. लॉगर और लॉगरेज के साथ रूबी में लॉगिंग

    रूबी में लॉग के साथ कार्य करना लॉगिंग उन प्राथमिक कार्यों में से एक है जिसे एक एप्लिकेशन आमतौर पर संबोधित करता है। लॉग का उपयोग तब किया जाता है जब आपको आवश्यकता होती है, उदाहरण के लिए, देखें कि आपके ऐप्स के अंदर क्या हो रहा है, उन पर नज़र रखें, या कुछ विशिष्ट डेटा के लिए मीट्रिक एकत्र करें। एक न