2011-04-05 14 views
5

मुझे लूप के लिए एक चर प्राप्त करने में परेशानी हो रही है। ऐसा लगता है कि i (var) की गणना बाद में कक्षा परिभाषा पर की जाती है, जिसकी मुझे पूरी आवश्यकता होती है।define_method जब तक विधि कहा जाता है चर का उपयोग नहीं कर रहा है?

ree-1.8.7-2010.02 > class Pat 
ree-1.8.7-2010.02 ?> for i in 39..47 
ree-1.8.7-2010.02 ?> define_method("a#{i}".to_sym) do 
ree-1.8.7-2010.02 >   puts i 
ree-1.8.7-2010.02 ?>  end 
ree-1.8.7-2010.02 ?> end 
ree-1.8.7-2010.02 ?> end 
#=> 39..47 

ree-1.8.7-2010.02 > p = Pat.new 
#=> #<Pat:0x103c31140> 

ree-1.8.7-2010.02 > p.a39 
47 
#=> nil 

ree-1.8.7-2010.02 > p.a49 
NoMethodError: undefined method `a49' for #<Pat:0x103c31140> 
    from (irb):69 
    from :0 
ree-1.8.7-2010.02 > p.a40 
47 
#=> nil 

क्या मुझे डीफ़ का उपयोग करना चाहिए? यदि हां, तो मैं गतिशील विधि नामों को कैसे प्राप्त कर सकता हूं जिन्हें मैंने यहां डीफ़ के साथ हासिल किया था।

उत्तर

7

क्या हो रहा है वहाँ थोड़ा सूक्ष्म है ... लूप के लिए पारंपरिक है कि आप सभी पुनरावृत्तियों में एकल "i" चर का उपयोग कर रहे हैं ... बंद करें (define_method के लिए ब्लॉक पासवर्ड) "i" को कैप्चर कर रहा है - और चूंकि केवल एक ही है "मैं", वे सभी (लूप के अंत में) "i" के अंतिम मान को कैप्चर करेंगे, जो उस सीमा में अंतिम मान है जिसे आप लूप कर रहे हैं।

वैकल्पिक समाधान:

class C 
    (1..10).each {|i| define_method("a#{i}") { puts i } } 
end 
3
>> class Pat 
.. (37..47). each do |i| 
..  define_method("a#{i}".to_sym) do 
..   puts i 
..  end 
..  end 
.. end #=> 37..47 
>> Pat.new.a40 #=> nil 
40 
>> Pat.new.a50 
NoMethodError: undefined method `a50' for #<Pat:0x00000100b39bc8> 

संपादित करें: माफ करना मैं एक उचित स्पष्टीकरण के लिए समय नहीं है, लेकिन एक त्वरित खोज एक ब्लॉग पोस्ट जहां आप इसे का सार प्राप्त करने में सक्षम हो जाएगा लाया: http://paulphilippov.com/articles/enumerableeach_vs_for_loops_in_ruby

2

हालांकि @ RyanLeCompte का जवाब बेहतर और क्लीनर है (और पर्याप्त समस्या के कारण का वर्णन करता है), यहाँ कोई वैकल्पिक समाधान, जिस तरह से इस समस्या को आम तौर पर जावास्क्रिप्ट में से बचा जाता है के बाद फैशन है:

class Foo 
    for i in 1..9 do 
    define_method "a#{i}", &(lambda{|x| lambda{puts x}})[i] 
    end 
end 
Foo.new.a1 
#=> 1 
Foo.new.a9 
#=> 9 

इस जवाब स्वीकार न करें, लेकिन यह वोट अप करते हैं तो यह आप अपने metaprogramming स्तर में मदद करता है। :)

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