2014-11-08 5 views
5
class Foo 
    def self.run(n,code) 
    foo = self.new(n) 
    @env = foo.instance_eval{ binding } 
    @env.eval(code) 
    end 
    def initialize(n) 
    @n = n 
    end 
end 

Foo.run(42, "p @n, defined? foo") 
#=> 42 
#=> "local-variable" 

उपरोक्त नमूना कार्यक्रम का उद्देश्य Foo उदाहरण के दायरे में मनमाने ढंग से कोड का मूल्यांकन करना है। यह ऐसा करता है, लेकिन बाध्यकारी code विधि से स्थानीय चर के साथ "प्रदूषित" है। मैं eval'd कोड के लिए दृश्यमान होने के लिए foo, n, या code नहीं चाहता। वांछित आउटपुट है:किसी ऑब्जेक्ट के दायरे में रिक्त बाध्यकारी बनाएं

#=> 42 
#=> nil 

मैं कैसे बना सकते हैं एक बंधन है कि (क) वस्तु उदाहरण के दायरे, लेकिन में (ख) किसी स्थानीय चर से रहित?


कारण यह है कि मैं सिर्फ instance_eval(code) का उपयोग करने का एक बाध्यकारी बजाय बनाने रहा हूँ कि real usage में मैं keep the binding around for later usage की जरूरत है, स्थानीय यह में बनाया चर रक्षा करना है।

उत्तर

4

ऐसा क्यों है? या क्या मुझे यहां कुछ महत्वपूर्ण याद आया?

class Foo 
    attr_reader :b 

    def initialize(n) 
    @n = n 
    @b = binding 
    end 

    def self.run(n, code) 
    foo = self.new(n) 
    foo.b.eval(code) 
    end 
end 

Foo.run(42, "p @n, defined?(foo)") 
# 42 
# nil 

या इसे आगे नीचे भी कम संदर्भ के लिए ले जाने के

class Foo 
    def initialize(n) 
    @n = n 
    end 

    def b 
    @b ||= binding 
    end 

    def self.run(n, code) 
    foo = self.new(n) 
    foo.b.eval(code) 
    end 
end 

Foo.run(42, "p @n, defined?(foo), defined?(n)") 
# 42 
# nil 
# nil 
+0

आपने कुछ स्थानीय चर हटा दिए हैं, लेकिन सभी नहीं: 'परिभाषित? (एन)' ''स्थानीय-परिवर्तनीय' है, जहां आपने 'बाध्यकारी' कहा था। यह क्लीनर है, लेकिन यह खाली नहीं है। – Phrogz

+0

अद्यतन संस्करण रिक्त है? – phoet

+0

हां, अद्यतन संस्करण काम करता है। धन्यवाद! नोट, हालांकि, यह हर बार 'बी' कहा जाता है जब यह एक नया खाली बाध्यकारी बनाता है। यदि आप यही चाहते हैं, तो जवाब सही है। अगर इसके बजाय मुझे-आप प्रत्येक रन से स्थानीय चर को जमा करने के लिए एक ही बाध्यकारी रखना चाहते हैं, तो आपको कुछ डीफ बी जैसे कुछ करने की आवश्यकता होगी; @b || = बाध्यकारी; end'।मैं आपको स्वीकृति दूंगा क्योंकि उदाहरण के प्रयोग से कुछ तरीकों से भंडारण एक अलग वस्तु (मेरे उत्तर में) की तुलना में अधिक सुरुचिपूर्ण है; अन्य तरीकों से यह आपके ऑब्जेक्ट पर एक नया इंस्टेंस वैरिएबल लागू करता है जिसे आप नहीं चाहते हैं। – Phrogz

1

उत्तर:

module BlankBinding 
    def self.for(object) 
    @object = object 
    create 
    end 
    def self.create 
    @object.instance_eval{ binding } 
    end 
end 

विवरण:

आदेश में के साथ एक बाध्यकारी पाने के लिए कोई स्थानीय varia ब्लेस, आपको बिना किसी के दायरे में binding पर कॉल करना होगा। किसी विधि को कॉल करने से स्थानीय चर रीसेट हो जाते हैं, इसलिए हमें ऐसा करने की आवश्यकता है। हालांकि, हम कुछ इस तरह करते हैं:

def blank_binding_for(obj) 
    obj.instance_eval{ binding } 
end 

... जिसके परिणामस्वरूप बाध्यकारी एक obj स्थानीय चर होगा। तुम इतनी तरह इस तथ्य को छुपा सकते हैं:

def blank_binding_for(_) 
    _.instance_eval{ binding }.tap{ |b| b.eval("_=nil") } 
end 

... लेकिन यह केवल स्थानीय चर के मूल्य को हटा। (वर्तमान में रुबी में remove_local_variable विधि नहीं है।) यह पर्याप्त है यदि आप आईआरबी या ripl जैसे किसी बाध्यकारी का उपयोग करने जा रहे हैं, जहां _ चर प्रत्येक मूल्यांकन के बाद सेट किया गया है, और इस प्रकार आपकी छाया पर चल जाएगा।

हालांकि, जैसा कि शीर्ष पर उत्तर में दिखाया गया है, एक विधि के लिए मूल्य पारित करने का एक और तरीका है, और यह एक आवृत्ति चर (या कक्षा परिवर्तनीय, या वैश्विक चर) के माध्यम से है। चूंकि हम का उपयोग हमारे ऑब्जेक्ट पर self को स्थानांतरित करने के लिए कर रहे हैं, इसलिए विधि को आमंत्रित करने के लिए हम जो भी आवृत्ति चर बनाते हैं, वह बाध्यकारी में उपलब्ध नहीं होगा।

संबंधित मुद्दे