In Ruby, is there no way to dynamically define a local variable in the current context? [duplicate]

旧巷老猫 提交于 2019-11-28 10:03:38

It seems that Ruby's magic would provide a way, but according to Matz, this was only possible in 1.8 via eval and only in certain contexts (i.e. irb). As of 1.9, this behavior was taken out ("strictly forbidden"):

Matz himself weighs in here: https://www.ruby-forum.com/topic/155673#685906

I read from somewhere that now Ruby can't dynamically create local variable. Is it true or just a bug?

The local variables are created in compile time, so that local variables that are defined in eval() cannot be accessed outside of eval. In 1.8, irb and tryruby does line by line compilation so that local variables are spilled from eval(), but in 1.9, it's strictly prohibited even under line-by-line compilation.

          matz.

(Non-sequitur alternative here, for anyone who wants something like this but not the exact technical situation that the questioner has):

Use a hash:

local_hash = {}

my_vars.each_pair do |k,v|
   local_hash[k] = v
end

puts local_hash['foo']
#=> 'baz'

In the context of creating the local variable itself, it is true there are some difficulties to overcome, however assigning dynamically is still no problem.

>> my_lv = 0
=> 0
>> instance_eval("#{'my_lv'} = 42")
=> 42
>> my_lv
=> 42

So, simply create from a gathered input (from gets, chomped or stripped as needed, it will just naturally end up as a string) and call to_sym on it and stuff the new symbol into local_variables and eval away...

>> local_variables << :my_created_lv
=> [:my_lv,
 :__,
 :_,
 :_dir_,
 :_file_,
 :_ex_,
 :_pry_,
 :_out_,
 :_in_,
 :my_created_lv]
>> 

Then you take the gathered string that you converted to a symbol, and assigned to in the code shown above, and eval it to get the value.

>> eval :my_lv.to_s
>> 24

As noted in another answer, I am unable to easily replicate this outside of Pry or IRB.

This has changed in future versions of Ruby, as Matz has removed and works hard to make this no longer able to happen.

Would a class instance variable work for you?

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

If not, please elaborate on the context and how you would use the local variable.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!