我想写一个方法(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,但还没有找到任何人。
我想写一个方法(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 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),和我劝阻使用上面提到的任何“解决方法”。
一致认为这是一个倒退,安德鲁的解释是正确的。如果你的使用情况是定义的变量,但是,已经有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
以上是你越已经发布,而如何将代码内工作的例子比推荐。
用实例/类变量绕过整个范围问题肯定会让'')''更容易推理。 – 2012-02-12 03:10:09
我试图看看我可以用给定的代码来完成工作。看着这很聪明。 – ericraio 2012-02-12 03:19:31
这是什么实际使用情况?这对我来说似乎倒退了。 – 2012-02-12 02:42:34
如果您想利用在已传递的块内进行的一些计算,最好的办法是从该块返回一些内容并对其进行处理。依赖传递的proc中的局部变量的命名没有多大意义。什么是保证某人使用“a”作为变量?当你不想要的时候,你会如何防止任意proc跺跺自己的变量? – 2012-02-12 04:24:39
我想为简单的控制台游戏制作一个'GameWorld'模块,这个模块有'load'和'run'方法。 load方法加载game_objects并将它们存储在数组中,'run'来描述它们之间的一些交互。在GameWorld的范围中,我可以访问game_objects数组并输出一些信息(健康状况,分数等)。只是为了“对称”和学习的目的,我试图用这两种方法使用块。现在,我将对象直接加载到模块的常量“game_objects”中。无论如何,非常感谢您的帮助,现在我们越来越清楚范围和区块的工作方式。 – evfwcqcg 2012-02-12 04:54:08