【问题标题】:Defining a method that checks the existence of a variable定义一个检查变量是否存在的方法
【发布时间】:2016-08-17 18:10:01
【问题描述】:

是否可以定义一个方法a?,当a存在时返回true,当a未定义时返回false

以下代码不起作用,因为当defined? a 被执行时,变量a 超出了它的范围。

a = 123

def a?
    if defined? a
        return true
    else
        return false
    end
end

puts a? # false

是否可以让我的代码的最后一行返回true

【问题讨论】:

    标签: ruby


    【解决方案1】:

    不,这是不可能的。局部变量被称为“局部变量”,因为它们在定义它们的范围内是局部的。它们按定义在其他范围内不存在。

    可以做的,是通过调用Kernel#binding 将本地范围重新定义为Binding 对象,然后使用Binding 检查是否定义了本地变量Binding#local_variable_defined?方法:

    def a?(binding)
      binding.local_variable_defined?(:a)
    end
    
    a?(binding)
    # => false
    
    a = 42 if false
    
    a?(binding)
    # => true
    
    a
    # => nil
    

    或者,更笼统地说:

    def local_variable_defined?(name, binding)
      binding.local_variable_defined?(name)
    end
    
    local_variable_defined?(:a, binding)
    # => false
    
    a = 42 if false
    
    local_variable_defined?(:a, binding)
    # => true
    
    a
    # => nil
    

    【讨论】:

    • lyen。我很困惑。您选择了一个声称(错误地)做您想做的事情的答案,但 Jörg 已经解释了为什么这是不可能的。
    • 我选择了 SamFarmer 的答案,因为我修改了他的代码,例如 this。我没有完全遵循他的代码。
    【解决方案2】:

    根据给定变量/对象的存在,定义自身返回 nil 或 true。

    您应该直接使用defined? 方法,而不是使用其他方法:

    if defined?a 
        puts  "defined"
    else 
        puts "not defined"
    end 
    a = 10
    
    if  defined?a 
        puts "defined a: #{a}"
    else
        puts "not defined"
    end
    

    输出:

    not defined
    defined a: 10
    

    【讨论】:

    • 也许是这样,但你没有回答这个问题或解释为什么 OP 不能做他或她想做的事。
    【解决方案3】:

    在 ruby​​ 中,关键字 def 充当范围门,因此您无法访问在方法定义之外定义的局部变量。或者,您可以使用块定义方法,允许您访问在方法定义之外定义的变量。

    a = '123'
    
    define_method 'a?' do 
      defined? a
    end
    

    有关这方面的更多信息,我强烈建议您阅读元编程 Ruby 的第一部分

    【讨论】:

    • 假设 a 在创建方法时没有定义。 a? 现在将返回 nil。现在将a 设置为“123”(或任何值)并再次执行a?。它仍然会返回零。那是因为您通过执行define_method 'a?' { nil } 创建了该方法。如果a 已被定义(等于任何东西),您将执行define_method 'a?' { "local-variable" }。例如,参见关键字defined?this description。反对票是我的。
    • 啊,我没有意识到它的行为方式是这样的。谢谢,我学到了一些新东西,我同意这不应该是公认的答案。
    • @SamFarmer,我选择你的答案是因为我将你的代码修改为define_method 'a?' do if defined? a return true else return false end end我没有完全按照你写的代码。
    • 我将代码粘贴到gist
    • 尝试在方法定义后定义a,方法会返回false。
    猜你喜欢
    • 2012-08-20
    • 2010-09-22
    • 2018-09-09
    • 2010-10-19
    • 2013-05-19
    • 2014-09-08
    • 2022-01-08
    相关资源
    最近更新 更多