在Ruby中,没有办法在当前上下文中动态定义局部变量吗?
我想知道是否有一种方法可以让我在当前上下文中动态定义一个先前未定义的变量。 例如:
foo # => NameError: undefined method or local variable ... # Some method call which sets foo = 1 in the local context foo # => 1
换句话说,假设foo
未定义,我正在寻找任何代码,可以让我在不使用foo
变量的情况下定义局部变量foo
(例如,如果我有一些其他变量bar
其值为:foo
,我不得不依赖在那上面设置foo
的值)。
似乎eval('foo = 1')
或eval('foo = 1', binding)
或者在Ruby 2.1中, binding.local_variable_set(:foo, 1)
都等效于:
1.times do foo = 1 end
换句话说,它们在新的本地上下文的上下文中设置foo
,使得该值在该上下文之外是不可访问的。
我正在寻找可能吗?
更新:此问题并非特定于任何特定的局部变量上下文(模块/类,方法,过程,块等)。 我有兴趣明确知道它可以或不可以完成的任何背景。
似乎Ruby的魔力会提供一种方式,但根据Matz的说法,这只能通过eval
1.8并且只能在某些情况下(即irb
)。 从1.9开始,这种行为被取消(“严格禁止”):
Matz自己在这里称重: https : //www.ruby-forum.com/topic/155673#685906
我从某处读到,现在Ruby无法动态创建局部变量。 它是真的还是只是一个bug?
局部变量是在编译时创建的,因此在eval()之外定义的局部变量不能在eval之外访问。 在1.8中,irb和tryruby逐行编译,以便局部变量从eval()溢出,但在1.9中,即使在逐行编译中也是严格禁止的。
matz.
(这里的非替代选择,对于任何想要这样的东西而不是提问者所具有的确切技术情况的人):
使用哈希:
local_hash = {} my_vars.each_pair do |k,v| local_hash[k] = v end puts local_hash['foo'] #=> 'baz'
在创建局部变量本身的上下文中,确实存在一些需要克服的困难,但是动态分配仍然没有问题。
>> my_lv = 0 => 0 >> instance_eval("#{'my_lv'} = 42") => 42 >> my_lv => 42
因此,只需从收集的输入中创建(根据需要从gets
,选择或剥离,它将自然地最终作为字符串)并在其上调用to_sym
并将新符号填充到local_variables
并eval away …
>> local_variables << :my_created_lv => [:my_lv, :__, :_, :_dir_, :_file_, :_ex_, :_pry_, :_out_, :_in_, :my_created_lv] >>
然后,将您转换为符号的聚集字符串,并在上面显示的代码中分配,并评估它以获取值。
>> eval :my_lv.to_s >> 24
如另一个答案所述,我无法在Pry或IRB之外轻易复制此内容。
这在Ruby的未来版本中已经发生了变化,因为Matz已经删除并努力使其不再能够发生。
类实例变量是否适合您?
class Cat end Cat.instance_variable_set '@last_words', 'meow, meow, me...' Cat.instance_variable_get '@last_words' # => "meow, meow, me..." Cat.new.instance_variable_get '@last_words' # => nil
如果没有,请详细说明上下文以及如何使用局部变量。