代码之家  ›  专栏  ›  技术社区  ›  Aaron Yodaiken Stephen Chung

const\u get but for变量

  •  1
  • Aaron Yodaiken Stephen Chung  · 技术社区  · 14 年前

    所以我知道你可以说Kernel.const\u get(“ClassName”),然后你会得到这个字符串在名称上对应的类。但是对于变量呢?有没有办法做到:

    test = "heyas"
    some_method_here("test") #=> "heyas"
    

    非常感谢

    事实上,我需要更复杂的代码,例如:

    class User
      class Validations
        class << self
          def username_len
            return u.len > 3 and u.len < 22
          end
          # ...
        end
      end
      def validate(u,e,p)
        [:u, :e, :p].each do |v|
          Validations.send(:define_singleton_method, v, lambda { eval(v.to_s) }) # see this line
        end
        #other code to run validations
      end
    end
    

    所以你看,没有更好的办法了,是吗?

    4 回复  |  直到 14 年前
        1
  •  4
  •   Jörg W Mittag    14 年前

    class_variable_get , instance_variable_get const_get local_variable_get . 但无论如何,这是没有意义的:局部变量是当前方法体、模块体、类体或脚本体的局部变量,这就是为什么它们是局部变量 打电话 从其他方法访问它们。

    有没有办法做到:

    test = "heyas"
    some_method_here("test") #=> "heyas"
    

    不,这是不可能的。在那里 不可能是 一种方法。 test 地方的 变量,也就是说 只有 没有 存在于身体内部 some_method_here 整点 局部变量:在任何情况下,都不能从其他地方访问它们。

    def my_func(str)
      var_a = 'hey'
      var_b = 'ah'
      return some_method_here(str)
    end
    #=> should return the corresponding variable's value, e.g. my_func('var_a')
    #=> 'hey'
    

    再说一遍,这个 不可能 工作,自从 整点 不能

    但有一个非常简单的变化,它正是你想要的:

    def my_func(str)
      {
        'var_a' => 'hey',
        'var_b' => 'ah'
      }[str]
    end
    #=> should return the corresponding variable's value, e.g. my_func('var_a')
    #=> 'hey'
    

    my_func = {'var_a' => 'hey', 'var_b' => 'ah'}
    #=> should return the corresponding variable's value, e.g. my_func['var_a']
    #=> 'hey'
    

    考虑到只能传入有限数量的不同选项,最好使用符号:

    my_func = {var_a: 'hey', var_b: 'ah'}
    #=> should return the corresponding variable's value, e.g. my_func[:var_a]
    #=> 'hey'
    

    你问的基本上是:传入一个键,得到一个值。那是 确切地 多棒的 Hash

    编辑:经过修改后的问题,这是我能想到的最好的:

    def validate(u, e, p)
      local_variables.zip(local_variables.map {|var|
        eval(var.to_s)
      }).each {|var, val|
        Validations.send(:define_singleton_method, var) { val }
      }
    end
    

    单子方法 属于 User::Validations 实例 属于 User . 根据 方法,则系统中只能有一个副本。但是你有很多不同的例子 ,每次你打电话 User#validate 覆盖 只有 User::Validations.u , User::Validations.e User::Validations.p 在这一点上,他们将开始完全不同的行为 系统。

    整个系统 单个实例 . 可能会有 许多实例

    那只是 不能 说得对。

    u1 = User.new
    u1.validate('u1', :e1, 1)
    
    p User::Validations.u, User::Validations.e, User::Validations.p
    # => 'u1'
    # => :e1
    # => 1
    
    u2 = User.new
    u2.validate('U2', :E2, 2.0)
    # =>  warning: method redefined; discarding old u
    # =>  warning: method redefined; discarding old e
    # =>  warning: method redefined; discarding old p
    #              ^^^^^^^^^^^^^^^^
    #                    Oops!
    
    p User::Validations.u, User::Validations.e, User::Validations.p
    # => 'U2'
    # => :E2
    # => 2.0
    #    ^^^
    # Completely different results for the exact same arguments
    
        2
  •  3
  •   theIV    14 年前

    也许我错过了什么,但你为什么不能这么做 test 为了得到它的价值?如果您正在定义实例变量,那么 instance_variable_get

    编辑:正如我在下面的评论中提到的,你可以这样做

    def my_func(str); var_a="hey"; var_b="ah"; eval str; end
    my_func('var_a') #=> "hey"
    

        3
  •  2
  •   horseyguy    14 年前

    试试这个:

    def validate(u,e,p)
        [[:u, u], [:e, e], [:p, p]].each do |v|
            Validations.send(:define_singleton_method, v.first, lambda { v.last }) 
        end  
    end
    

    或者

    def validate(u,e,p)
        {:u => u, :e => e, :p => p}.each do |k, v|
            Validations.send(:define_singleton_method, k, lambda { v }) 
        end  
    end
    
        4
  •  1
  •   Kai Stinchcombe    11 年前

    eval("#{var_name}")
    

    我会的。显然不要用不可信的输入运行。如果要避免未定义变量的错误,可以使用:

    eval("#{var_name}") if eval("defined?(#{var_name})") == 'local-variable'
    

    例如。

    test = 'heyas'
    var_name = :test
    eval("#{var_name}") if eval("defined?(#{var_name})") == 'local-variable' #=> "heyas"
    var_name = :not_set
    eval("#{var_name}") if eval("defined?(#{var_name})") == 'local-variable' #=> "nil"
    

    在edge ruby上,定义如下:

    Binding#local_variable_defined?
    Binding#local_variable_get
    Binding#local_variable_set
    

    因此,在未来的版本中,您可能可以直接使用这些调用。