我知道还有其他类似问题,例如:
但答案并不完全令人满意。
我有:
ruby-1.9.2-p290 :001 > a=Hash.new
=> {}
ruby-1.9.2-p290 :002 > a['one']="hello"
=> "hello"
ruby-1.9.2-p290 :006 > defined?(a['one']['some']).nil?
=> false
ruby-1.9.2-p290 :007 > a['one']['some'].nil?
=> true
似乎:
if a['one']['some'].nil?
a['one']['some']=Array.new
end
就足够了。它是否正确?这对任何数据类型都是正确的吗?被定义为?在这种情况下需要吗?
THX
答案 0 :(得分:2)
你似乎混淆了两个概念。一种是定义变量,另一种是定义Hash键。由于哈希在某个时刻是变量,因此必须对其进行定义。
defined?(a)
# => nil
a = { }
# => {}
defined?(a)
# => "local-variable"
a.key?('one')
# => false
a['one'] = 'hello'
# => 'hello'
a.key?('one')
# => true
某些东西可以是一个密钥,同时nil
,这是有效的。哈希没有定义或未定义的概念。关键是否存在是关键所在。
使用.nil?
进行测试的唯一原因是要区分两个可能的非真值:nil
和false
。如果您永远不会在该上下文中使用false
,那么调用.nil?
会产生不必要的冗长。换句话说,if (x.nil?)
相当于if (x)
提供的x
永远不会是字面false
。
您可能想要使用的是||=
模式,如果现有值为nil
或false
,则会分配一些内容:
# Assign an array to this Hash key if nothing is stored there
a['one']['hello'] ||= [ ]
更新:根据Bruce的评论进行了编辑。
答案 1 :(得分:2)
我不得不深入挖掘Google的一些页面,但我最终从Ruby 1.9规范中找到了this useful bit:
“在所有情况下,测试[定义?]是在不评估操作数的情况下进行的。”
所以正在发生的事情是:
a['one']['some']
并说“正在向'a'对象发送”operator []“消息 - 这是一个方法调用!”和定义的结果?那是“方法”。
然后当你检查nil?时,字符串“method”显然不是nil。
答案 2 :(得分:1)
除了@tadmans的回答,你在你的例子中实际做的是检查字符串"some"
是否包含在字符串"hello"
中,该字符串存储在位置{{ 1}}。
"one"
一个更简单的例子:
a = {}
a['one'] = 'hello'
a['one']['some'] # searches the string "some" in the hash at key "one"
这就是为什么b = 'hello'
b['he'] # => 'he'
b['ha'] # => nil
方法没有像您预期的那样返回defined?
,而是nil
。