Ruby定义了?(42 [0] [:foo])&& defined?(93 [0] ["bar"])== true.为什么?

Aut*_*ico 4 ruby defined

短篇故事:

"为什么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
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

好吧,method2在这里被称为.它发生在junk一个fixnum时.

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

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

Aru*_*hit 6

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
Run Code Online (Sandbox Code Playgroud)

现在谈到你的观点: -

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

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

  • 是啊.`3 [0] [:whatever]`产生错误,但错误*不是*方法未定义. (3认同)