10

我想知道是否有一种方法可以让我在当前上下文中动态定义以前未定义的变量。例如:

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

在 Ruby 2.1 中,eval('foo = 1')or or似乎都等价于:eval('foo = 1', binding)binding.local_variable_set(:foo, 1)

1.times do
  foo = 1
end

换句话说,它们设置foo在一个的本地上下文的上下文中,使得该值在该上下文之外是不可访问的。

我想做的事可能吗?

更新:这个问题并不特定于任何特定的局部变量上下文(模块/类、方法、过程、块等)。我有兴趣明确了解可以或不能完成的任何上下文。

4

3 回答 3

10

似乎 Ruby 的魔法会提供一种方法,但根据 Matz 的说法,这只能在 1.8 via 中实现,eval并且只能在某些上下文中(即irb)。从 1.9 开始,这种行为被取消(“严格禁止”):

马茨本人在这里称重:https ://www.ruby-forum.com/topic/155673#685906

我从某个地方读到现在 Ruby 无法动态创建局部变量。这是真的还是只是一个错误?

局部变量是在编译时创建的,因此在 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'
于 2013-10-11T17:22:16.773 回答
2

在创建局部变量本身的上下文中,确实有一些困难需要克服,但是动态分配仍然没有问题。

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

因此,只需从收集的输入中创建(gets根据需要从、chomped 或剥离,它自然会以字符串结尾)并调用to_sym它并将新符号填充到local_variables并评估掉......

>> 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 已经删除并努力使这种情况不再发生。

于 2013-10-11T21:30:44.823 回答
0

类实例变量对你有用吗?

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

如果不是,请详细说明上下文以及如何使用局部变量。

于 2013-10-11T20:04:26.000 回答