我正在考虑这个安排:
if trie.nil?
trie = @hash[letter] = Trie.new(@level + 1)
end
并从右边开始解释它,如:
Trie
类创建一个新实例。@hash
哈希中的值,并由letter
密钥编制索引。trie
中,因此可以在别处使用。我有多接近? Trie
表的实例是否真的存储在哈希中?
答案 0 :(得分:2)
问题是逻辑不清楚。在一行上使用两个分配是等待中的维护问题。
相反,用两行代码编写代码会更清晰,更具惯用性:
trie = Trie.new(@level + 1) if trie.nil?
@hash[letter] = trie
或:
trie ||= Trie.new(@level + 1)
@hash[letter] = trie
第二个示例使用||=
检查trie
是否已初始化,即不是nil。如果它不是零,代码就会失效。如果 为nil,那么将为trie
分配新Trie实例的值。并且,在所有情况下,@hash[letter]
都会被分配当前值trie
。
这是一个很好的例子,当有人试图在代码中成为男子气概时会发生什么。 他们了解他们正在做什么,但他们让其他人都摸不着头脑,想知道两件事:
在代码审查中,听起来都不是一件好事,所以写下你的代码就好像其他人会在未来的路上阅读它一样,因为,某些人的意愿很好 - 无论是你,还是谁能维护你的代码 - 所以要善待。
答案 1 :(得分:1)
您的解释是正确的。
创建 Trie.new(@level + 1)
,返回值并分配给@hash[letter]
,然后返回相同的值,并将其分配给trie.
执行结束时,trie
和@hash[letter]
都会指向同一个新创建的Trie
实例。
如果要创建新对象,则需要多次分配,需要将其缓存到某处(例如,用于记忆),但同时需要在同一方法中重用该变量并且要使用捷径。
假设您在同一范围内使用新创建的对象需要3行。您可以@hash[letter]
访问该对象,但trie
更短。当然,这只是可能的用法之一。
答案 2 :(得分:1)
是的,你是对的。
从右到左,每个代码块都在赋值之前执行
示例:
variable = nil
hash = {}
variable = hash[:key] = String.new("text")
variable #=> "text"
hash #=> {:key => "text"}
答案 3 :(得分:1)
你说得对,多项任务是正确的。这样做的原因是赋值构造的左侧必须是单个文字标记:在赋值foo = bar
中,bar
可能具有任意复杂性,但foo
必须是单一令牌;将一些复杂的表达式分配给单个名称是有意义的,但是为复杂的表达式赋值是没有意义的。所以如果你有a = b = c
,那么a = (b = c)
是理解它的唯一方法,那就是Ruby的工作方式。
关于将表保存为哈希值的问题可能对象太大了,这并不重要,因为所有保留的只是指向对象的指针。