在 Ruby 中动态设置局部变量
我对在 Ruby 中动态设置局部变量感兴趣。不创建方法、常量或实例变量。
所以类似:
args[:a] = 1
args.each_pair do |k,v|
Object.make_instance_var k,v
end
puts a
> 1
我特别想要局部变量,因为所讨论的方法存在于模型中,并且我不想污染全局或对象空间。
I'm interested in dynamically setting local variables in Ruby. Not creating methods, constants, or instance variables.
So something like:
args[:a] = 1
args.each_pair do |k,v|
Object.make_instance_var k,v
end
puts a
> 1
I want locally variables specifically because the method in question lives in a model and I dont want to pollute the global or object space.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
作为给未来读者的附加信息,从 ruby 2.1.0 开始,您可以使用
binding.local_variable_get
和binding.local_variable_set
:如 文档,它的行为类似于
As an additional information for future readers, starting from ruby 2.1.0 you can using
binding.local_variable_get
andbinding.local_variable_set
:As stated in the doc, it is a similar behavior to
这里的问题是each_pair 内的块具有不同的范围。其中分配的任何局部变量只能在其中访问。例如,这个:
产生这个:
为了解决这个问题,您可以创建一个本地散列,将键分配给这个散列,然后在那里访问它们,如下所示:
当然,在这个例子中,它只是复制原始散列键的字符串。不过,我假设实际的用例更复杂。
The problem here is that the block inside each_pair has a different scope. Any local variables assigned therein will only be accessible therein. For instance, this:
Produces this:
In order to get around this, you could create a local hash, assign keys to this hash, and access them there, like so:
Of course, in this example, it's merely copying the original hash with strings for keys. I'm assuming that the actual use-case, though, is more complex.
有趣的是,您可以更改局部变量,但不能设置它:
test =>
7
测试 =>
NameError: main:Object 的未定义局部变量或方法“x”
这是 Dorkus Prime 代码有效的唯一原因。
interesting, you can change a local variable but you cannot set it:
test =>
7
test =>
NameError: undefined local variable or method `x' for main:Object
This is the only reason why Dorkus Prime's code works.
我建议您使用哈希(但请继续阅读其他替代方案)。
为什么?
允许任意命名参数会导致代码极其不稳定。
假设您有一个方法
foo
,您想要接受这些理论上的命名参数。场景:
被调用的方法 (
foo
) 需要调用一个不带参数的私有方法(我们称之为bar
)。如果您向foo
传递一个想要存储在局部变量bar
中的参数,它将屏蔽bar
方法。解决方法是在调用bar
时使用显式括号。假设
foo
的代码分配了一个局部变量。但随后调用者决定传入一个与该局部变量同名的 arg。分配将破坏参数。基本上,方法的调用者永远不能改变方法的逻辑。
替代方案
另一种中间立场涉及
OpenStruct
。与使用哈希相比,它需要更少的输入。请注意,
OpenStruct
允许您访问不存在的成员 - 它将返回nil
。如果您想要更严格的版本,请改用Struct
。这将创建一个匿名类,然后实例化该类。
I suggest you use the hash (but keep reading for other alternatives).
Why?
Allowing arbitrary named arguments makes for extremely unstable code.
Let's say you have a method
foo
that you want to accept these theoretical named arguments.Scenarios:
The called method (
foo
) needs to call a private method (let's call itbar
) that takes no arguments. If you pass an argument tofoo
that you wanted to be stored in local variablebar
, it will mask thebar
method. The workaround is to have explicit parentheses when callingbar
.Let's say
foo
's code assigns a local variable. But then the caller decides to pass in an arg with the same name as that local variable. The assign will clobber the argument.Basically, a method's caller must never be able to alter the logic of the method.
Alternatives
An alternate middle ground involves
OpenStruct
. It's less typing than using a hash.Note that
OpenStruct
allows you access non-existent members - it'll returnnil
. If you want a stricter version, useStruct
instead.This creates an anonymous class, then instantiates the class.
因为您不需要常量
2
您可能会发现这种方法很有趣(在正确的上下文中评估变量)
4
since you don't want constants
2
you might find this approach interesting ( evaluate the variables in the right context)
4