变量如何绑定到define_method的主体? [英] How are variables bound to the body of a define_method?
问题描述
在尝试提高我的Ruby技能的同时,我不断遇到这种情况,仅阅读API文档就无法找出解释.一个解释将不胜感激.这是示例代码:
While trying to brush up my Ruby skills I keep running across this case which I can't figure out an explanation for by just reading the API docs. An explanation would be greatly appreciated. Here's the example code:
for name in [ :new, :create, :destroy ]
define_method("test_#{name}") do
puts name
end
end
我希望/期望发生的事情是name
变量将绑定到给define_method
的块,并且当调用#test_new
时它将输出"new".相反,每个定义的方法都输出"destroy"(销毁),即分配给name变量的最后一个值.我对define_method
及其代码块有什么误解?谢谢!
What I want/expect to happen is that the name
variable will be bound to the block given to define_method
and that when #test_new
is called it will output "new". Instead each defined method outputs "destroy" -- the last value assigned to the name variable. What am I misunderstanding about define_method
and its blocks? Thanks!
推荐答案
Ruby中的块是闭包的:传递给define_method
的块捕获变量name
本身(而不是其值),因此只要该块被调用.那是难题的第一步.
Blocks in Ruby are closures: the block you pass to define_method
captures the variable name
itself–not its value—so that it remains in scope whenever that block is called. That's the first piece of the puzzle.
第二部分是define_method
定义的方法是块本身.基本上,它将Proc
对象(传递给它的块)转换为Method
对象,并将其绑定到接收器.
The second piece is that the method defined by define_method
is the block itself. Basically, it converts a Proc
object (the block passed to it) into a Method
object, and binds it to the receiver.
所以最终得到的是方法,该方法捕获(关闭了)变量name
,该变量在循环完成时设置为:destroy
.
So what you end up with is a method that has captured (is closed over) the variable name
, which by the time your loop completes is set to :destroy
.
添加:for ... in
构造实际上创建了一个新的局部变量,相应的[ ... ].each {|name| ... }
构造将不起作用.也就是说,您的for ... in
循环等效于以下内容(无论如何在Ruby 1.8中):
Addition: The for ... in
construction actually creates a new local variable, which the corresponding [ ... ].each {|name| ... }
construction would not do. That is, your for ... in
loop is equivalent to the following (in Ruby 1.8 anyway):
name = nil
[ :new, :create, :destroy ].each do |name|
define_method("test_#{name}") do
puts name
end
end
name # => :destroy
这篇关于变量如何绑定到define_method的主体?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!