【问题标题】:Ruby defined?( 42[0][:foo] ) && defined?( 93[0]["bar"] ) == true. Why?Ruby 定义?(42[0][:foo])&& 定义?(93[0]["bar"])== true。为什么?
【发布时间】:2014-05-13 23:17:08
【问题描述】:

短篇小说:

“为什么defined?(59[0][:whatever]) 评估为真?”


长篇大论:

我最近遇到了一些奇怪的行为,这让我很反感。

我正在开发一种对数据进行一些清洗的方法:

#Me washing input data:
def foo(data)
  unless data && defined?(data[0]) && defined?(data[0][:some_param])
    method2(data[0][:some_param])
  else
    freak_out()
  end
end

我通常会编写测试,在其中吐出各种垃圾数据,以确保不会发生任何奇怪的事情:

describe "nice description" do
  it "does not call method2 on junk data" do
    expect(some_subject).to_not receive(:method2)
    random_junk_data_array.each do |junk|
      some_subject.foo(junk)
    end
  end
end

嗯,method2 是在这里调用的。它发生在 junk 是一个固定数字时。

我正在使用ruby 2.1.0,我可以看到Fixnum 有一个#[] 方法可以获取该位置的位,很好。

但是为什么fixnum[0][:some_param] 被认为是defined

【问题讨论】:

    标签: ruby defined


    【解决方案1】:

    defined? 表达式 测试表达式是否引用任何可识别的对象(文字对象、已初始化的局部变量、从当前范围可见的方法名称等)。如果表达式无法解析,则返回值为nil否则,返回值提供有关表达式的信息。

    让我用一个例子来解释:-

    defined?("a") # => "expression"
    # this returns "method", as there is a method defined on the class String. So, the
    # method invocation is possible, and this is a method call, thus returning `"method"`.
    defined?("a".ord) # => "method"
    # it return nil as there is no method `foo` defined on `"a"`, 
    # so the call is not possible.
    defined?("a".foo) # => nil
    

    现在进入你的观点:-

    正如你所说,data[0] 给出了一个Fixnum 实例,当然Fixnum#[] 存在。因此fixnum_instance[:some_param] 也是一个有效的方法调用。它只是测试该方法是否已定义。如果定义,它将告诉是 这是一个"method" 表达式。否则nil。 Not 实际上会检查方法调用是否成功。

    在 Ruby 中,除了 nilfalse 之外,所有对象都有 truthy 值,因此 "method" 作为字符串对象也具有 truthy 值,因此您的条件成功了。

    【讨论】:

    • 是的。 3[0][:whatever] 产生错误,但错误不是方法未定义。
    • 我明白了。它本质上是一个begin catch,它只检查not defined error,如果它捕捉到它,则返回nil,如果没有,则返回某种形式的“true”。
    猜你喜欢
    • 1970-01-01
    • 2020-02-24
    • 2016-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多