【问题标题】:Is there a way to implicitly evaluate variables in ruby?有没有办法在 ruby​​ 中隐式评估变量?
【发布时间】:2014-08-07 04:59:12
【问题描述】:

在 PHP 中,我可以这样做:

$a = 1;
$c = 'a';
$$c = 2;
//now $a == 2

在 ruby​​ 中是否有任何等价物?我的意思是,有什么简单的方法可以在这样的执行过程中取消引用变量吗?我宁愿不使用 eval,因为它看起来很乱——我已经确定 eval 不能作为字符串的方法调用。

【问题讨论】:

  • @IvayloStrandjev 你的链接是关于实例变量的
  • @Geoffroy 这就是为什么我没有发布答案而是发表评论的原因。这两个问题是相关的,该链接提供了有关所提问题的一些见解。
  • 重要的一点是,即使有一些方法可以在 ruby​​ 中使用“变量”,您真的不应该这样做,因为它可能导致潜在的严重安全问题, 相当慢并且总体上是糟糕的设计,导致数据访问不明确并促进全局变量(这是有史以来最糟糕的事情)。相反,您应该将数据放入哈希中,即data = {:a => 1},然后您可以将其作为data[:a] 访问。

标签: ruby pointers eval dereference


【解决方案1】:

这是可能的,但它有点复杂。你实际上有两种可能性:

Kernel#local_variables

返回当前局部变量的名称。

fred = 1
for i in 1..10
   # ...
end
local_variables   #=> [:fred, :i]

Binding#local_variable_get/set

返回一个局部变量符号的值。

def foo
  a = 1
  binding.local_variable_get(:a) #=> 1
  binding.local_variable_get(:b) #=> NameError
end

此方法是以下代码的简短版本。

binding.eval("#{symbol}")

【讨论】:

    【解决方案2】:

    如果你只需要这个,你可以这样做

    a = 1
    c = 'a'
    eval("#{c} = 2")
    a == 2   # => true
    

    ...但这是愚蠢的做法

    如果你需要这个作为实例变量

    class Foo
      attr_reader :a
    
      def initialize
        @a = 1
      end
    end
    
    foo = Foo.new
    foo.instance_variable_get(:a)       #=> 1
    foo.a                               #=> 1
    foo.instance_variable_set(:"@a", 2)
    foo.a                               #=> 2
    

    ...您也可以像这样评估实例:

    # ...
    foo.instance_eval do
      @a = 'b'
    end
    foo.a    # => 'b'
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-24
      • 2012-06-28
      • 1970-01-01
      • 2013-12-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多