【问题标题】:Undefine variable in Ruby在 Ruby 中取消定义变量
【发布时间】:2011-01-01 23:17:23
【问题描述】:

假设我使用的是irb,然后输入a = 5。如何删除a 的定义,以便键入a 返回NameError

一些上下文:稍后我想这样做:

context = Proc.new{}.binding
context.eval 'a = 5'
context.eval 'undef a'  # though this doesn't work.

【问题讨论】:

    标签: ruby metaprogramming local-variables


    【解决方案1】:

    本着问题的精神,您可以将变量限制在一个范围内,假设您可以将其他局部变量锁定在同一范围内。如果您在类中定义某些内容并且不希望局部变量留在类声明中,这尤其有用。

    我能想到的唯一方法是使用Integer#timesArray#each,如下所示:

    1.times do |a|
      a = 5
      # code…
    end
    
    [5].each do |a|
      # code…
    end
    

    除此之外,可能还有其他更简洁的方法来限制块。这些并不像我想要的那样干净,我很想看看是否有人有更清洁的方法可以做到这一点。

    【讨论】:

      【解决方案2】:

      remove_class_variableremove_instance_variableremove_const 方法,但目前没有等效于局部变量的方法。

      【讨论】:

      • 嗯,烦人的是没有这样的方法。我想我现在可以坚持使用实例变量。
      • 这些链接看起来不再是正确的地方了。
      • @jcollum 谢谢。 remove_instance_variableremove_const 是私有方法,因此似乎不再包含在 ruby​​-doc.org 上的文档中。我已经更新了答案以使用到 apidock.com 的等效链接
      【解决方案3】:

      您可以通过缩小变量存在的范围来避免取消声明变量:

      def scope 
        yield
      end
      
      scope do 
        b = 1234
      end
      
      b  # undefined local variable or method `b' for main:Object
      

      【讨论】:

      • 这是我想看到的答案。
      • 有一种标准的scope 函数称为Proc.new: Proc.new { b = 1 } ; b
      • 值得注意的是 Proc.new 与给定的 scope 不同之处在于它实际上并不调用块。相当于Proc.new { b = 1 }.call; b。您也可以使用lambda { b = 1 }.call
      【解决方案4】:

      您始终可以通过调用 irb 子 shell 来“清除”irb 的局部变量注册表。想想 Bash shell 如何处理未导出的环境变量。既然你提到了交互模式,这个解决方案应该可以解决这个问题。

      就生产代码而言,我不想取消定义局部变量作为解决方案的一部分 - 键控哈希可能更适合这种情况。

      这就是我的意思:

      $ irb
      irb(main):001:0> a = "a"
      => "a"
      irb(main):002:0> defined? a
      => "local-variable"
      irb(main):003:0> irb # step into subshell with its own locals
      irb#1(main):001:0> defined? a
      => nil
      irb#1(main):002:0> a
      NameError: undefined local variable or method `a' for main:Object
          from /Users/dean/.irbrc:108:in `method_missing'
          from (irb#1):2
      irb#1(main):003:0> exit
      => #<IRB::Irb: @context=#<IRB::Context:0x1011b48b8>, @signal_status=:IN_EVAL, @scanner=#<RubyLex:0x1011b3df0>>
      irb(main):004:0> a # now we're back and a exists again
      => "a"
      

      【讨论】:

      • 返回:“NotImplementedError: ruby engine can initialize only in the main thread
      【解决方案5】:

      目前你没有办法删除全局变量、局部变量和类变量。您可以使用“remove_const”方法删除常量

      【讨论】:

      • 类变量不正确 - 有 remove_class_variable。
      猜你喜欢
      • 1970-01-01
      • 2013-04-18
      • 2012-07-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多