Ruby定义的?(42[0][:foo])&&;已定义?(93[0][“条])==真。为什么?

Ruby定义的?(42[0][:foo])&&;已定义?(93[0][“条])==真。为什么?,ruby,defined,Ruby,Defined,短篇故事: “为什么定义?(59[0][:whatever])的计算结果为true?” 长话短说: 我最近遇到了一些奇怪的行为,这使我很反感 我正在开发一种对数据进行清洗的方法: #Me washing input data: def foo(data) unless data && defined?(data[0]) && defined?(data[0][:some_param]) method2(data[0][:some_param])

短篇故事:

“为什么
定义?(59[0][:whatever])
的计算结果为true?”
长话短说:

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

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

#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
是一个fixnum时

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

但是为什么
fixnum[0][:某些参数]
被认为是
定义的

表达式测试表达式是否引用任何可识别的对象(文本对象、已初始化的局部变量、从当前范围可见的方法名称等)。如果无法解析表达式,则返回值为
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\u实例[:some\u参数]
也是一个有效的方法调用。它只是测试方法是否已定义。如果已定义,它将告诉您是这是一个
的“方法”
表达式。否则
nil
。Not实际上将检查方法调用是否成功


在Ruby中,除了
nil
false
之外,所有对象都有truthy值,因此
作为字符串对象的“方法”
也有truthy值,因此您的条件成功了。

是的
3[0][:which]
产生错误,但错误不是方法未定义。我明白了。它本质上是一个
开始捕获
,它只检查
未定义的错误
,如果捕获到它,则返回nil,如果没有,则返回某种形式的“true”。