Ruby:将变量导出到本地名称空间

时间:2011-08-11 02:37:29

标签: ruby reflection metaprogramming

我想以编程方式将新变量插入本地Ruby命名空间。例如,我希望能够写

label = 'some_name'
# some code equivalent to
#   some_name = 3
# but using only 'label' to get the name.
puts some_name  # returns 3

为了完成这项工作,我在这里放了什么?

3 个答案:

答案 0 :(得分:3)

我已经回答了另一个SO question similar to this。简短的回答是,如果你特别想要根据另一个变量的值创建一个名为它的局部变量,那么就没办法了。它只是想让看起来好像你已经创建了一个本地但它真的是红宝石魔法,那么@ mikong的答案就是一种方法。

请注意,如果您放松约束并乐于创建实例变量,那么可以执行此操作。

label = 'some_name'
self.instance_variable_set("#{label}", 3)
puts @some_name

你甚至可以动态定义一个访问者,然后你就可以摆脱难看的@,但你只需要一个伪装成本地而不是真正的局部变量的方法。

答案 1 :(得分:2)

label = 'some_name'
eval "#{label} = 3"
puts eval "#{label}"
puts local_variables

请注意,您可能永远不会有机会执行......

puts some_name

...因为如果您知道要创建的局部变量,就不需要使用运行时代码来命名它们。这很好,因为解释器将无法直接puts some_name,因为它从未解析some_name的赋值。但它 那里本地的,puts local_variables能够显示。

答案 2 :(得分:2)

以下不完全是您在上面提到的两行之间的代码:

class Example
  attr_accessor :label

  def method_missing(name, *args, &block)
    return some_processing  if name == label.to_sym
  end

  def some_processing
    3 # of course, this can be something more complicated
  end

  def test
    @label = 'some_name'
    puts some_name
  end

end

尽管如此,它似乎可以满足您的需求。机制已经从你给出的改变了(label现在是一个属性)。此外,从技术上讲,它不是变量,而是具有动态名称的方法,可以返回您需要的内容。

就个人而言,我认为您的要求似乎有点危险,因为“变量”名称会发生​​变化。我可能不会在我的例子中使用代码。我想根据项目要求,我会想到一个不同的方法。