添加到存储在哈希表中的列表有一个很好的习惯用法:
(hash[key] ||= []) << new_value
现在,假设我编写了一个衍生散列类,就像在 Hashie 中找到的那样,它对我存储在其中的任何散列进行深度转换。那么我存储的将与我传递给 = 运算符的对象不同;Hash 可以转换为 Mash 或 Clash,并且可以复制数组。
这就是问题所在。Ruby 显然从 var= 方法返回传入的值,而不是存储的值。var= 方法返回什么并不重要。下面的代码演示了这一点:
class C
attr_reader :foo
def foo=(value)
@foo = (value.is_a? Array) ? (value.clone) : value
end
end
c=C.new
puts "assignment: #{(c.foo ||= []) << 5}"
puts "c.foo is #{c.foo}"
puts "assignment: #{(c.foo ||= []) << 6}"
puts "c.foo is #{c.foo}"
输出是
assignment: [5]
c.foo is []
assignment: [6]
c.foo is [6]
当我将此作为错误发布给 Hashie 时,Danielle Sucher 解释了发生的事情并指出“foo.send :bar=, 1”返回 bar= 方法返回的值。(研究的提示!)所以我想我可以这样做:
c=C.new
puts "clunky assignment: #{(c.foo || c.send(:foo=, [])) << 5}"
puts "c.foo is #{c.foo}"
puts "assignment: #{(c.foo || c.send(:foo=, [])) << 6}"
puts "c.foo is #{c.foo}"
哪个打印
clunky assignment: [5]
c.foo is [5]
assignment: [5, 6]
c.foo is [5, 6]
有没有更优雅的方法来做到这一点?