是否可以在方法中访问块的范围?

我想编写方法( define_variables ),它可以获取一个block并使用其中定义的变量。 可能吗? 例如,我想输出5:

 module A def self.define_variables yield puts a # not 5 :( end end A::define_variables do a = 5 end 

也许有一些eval的技巧,但还没有找到任何人。

总之,没有。 在你调用yield之后,块中定义的变量就会消失 (我们将会看到),除了返回的内容 – 这就是范围的工作原理。 在你的例子中, 5仍然存在,因为它由块返回,因此puts yield将打印5 。 使用它你可以从块{:a => 5}返回一个哈希,然后以这种方式访问​​多个“变量”。 在Ruby 1.8( 仅限IRb )中,您可以:

 eval "a = 5" a # => 5 

虽然我不知道要eval一个块的内容。 无论如何, 在Ruby 1.9中, eval的范围是孤立的 ,这会给你一个NameError 。 您可以在Binding的上下文中执行eval

 def foo b = yield eval(a, b) + 2 end foo do a = 5 binding end # => 7 

在我看来,你想要做的是在Ruby中模拟宏,这是不可能的( 至少不是纯Ruby ),并且我不鼓励使用我上面提到的任何“解决方法”。

同意这有点倒退,安德鲁的解释是正确的。 但是,如果您的用例是定义变量,那么已经有class_variable_setinstance_variable_set方法对此非常有用:

 module A def self.define_variables(vars = {}) vars.each { |n, v| class_variable_set n, v } puts @@a end end A::define_variables :@@a => 5 

以上是一个如何在您发布的代码中工作而不是推荐的示例。