我想编写方法(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技巧,但还没有找到任何人。
答案 0 :(得分:5)
简而言之,没有。在您调用yield
之后,块中定义的那些变量已消失(有点像我们将要看到的),除了返回的内容 - 这就是范围的工作原理。在您的示例中,5
仍然存在,因为它由块返回,因此puts yield
将打印5
。使用此方法,您可以从块{:a => 5}
返回一个哈希值,然后以这种方式访问多个“变量”。在Ruby 1.8(在IRb only中),你可以这样做:
eval "a = 5"
a # => 5
虽然我不知道eval
块的内容。无论如何,in Ruby 1.9 the scope of eval
was isolated这会给你一个NameError
。您可以在Binding
的上下文中执行eval
:
def foo
b = yield
eval(a, b) + 2
end
foo do
a = 5
binding
end # => 7
在我看来,你要做的是在Ruby中模拟宏,这是不可能的(at least not pure Ruby),我不鼓励使用我提到的任何“变通办法”上方。
答案 1 :(得分:2)
同意这有点倒退,安德鲁的解释是正确的。但是,如果您的用例是定义变量,那么已有class_variable_set
和instance_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
上面更多的是如何在您发布的代码中工作而不是推荐的示例。