变量如何绑定到define_method的主体? [英] How are variables bound to the body of a define_method?

查看:74
本文介绍了变量如何绑定到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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆