define_method在调用方法之前不使用变量?

问题描述:

我无法从for循环获取变量。看来我(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 

我应该使用def吗?如果是这样的话,我如何才能实现我在def中实现的动态方法名称。

发生了什么事有一点微妙......您使用的传统for循环在所有迭代*享单个“i”变量......闭包(将密码设置为define_method)捕获“i” - 并且由于只有一个“我”,他们将(在for循环的结尾处)捕获“i”的最终值,这是您循环范围中的最后一个值。

替代解决方案:

class C 
    (1..10).each {|i| define_method("a#{i}") { puts i } } 
end 

>> 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

虽然@ RyanLeCompte的回答是更好的和更清洁的(和充分说明了问题的原因),这里是一个替代的解决方案,这个问题在JavaScript通常避免以后的路老式:

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 

不接受这个答案,但如果它可以帮助你的水平了你的元编程都投上一票。 :)