为什么将哈希集更新为变量更新该变量?

时间:2017-11-05 18:26:39

标签: ruby

我可以将哈希集更新为另一个变量,如下所示:

d = a = {b: 'c'}

a[:b] = 'qwerty'
d # => {:b=>'qwerty'} # What is this magic?

d[:b] = 'blah'
a # => {:b=>'blah'} # And this magic?

为什么在使用原始变量时不会发生这种情况?

d = a = 'b'

a = 'c'
d # =>'b' # Why is it still the same?

2 个答案:

答案 0 :(得分:5)

你做了两件非常不同的事情。

你的"原始变量"例如:

a = 'b'
d = a
a = 'c'

是一个简单的赋值,因此在第2行的末尾,ad引用相同的对象。然后在第3行,为a分配了一个新对象,ad最终引用了不同的对象。

你的第一个例子:

a = {b: 'c'}
d = a
a[:b] = 'qwerty'

是一个赋值,后跟一个调用其接收器的方法的调用。第三行也可以写成以下之一,使方法调用更加明确:

a.[]=(:b, 'qwerty')
a.send(:[]=, :b, 'qwerty')

所以你要将变异方法调用的赋值与一系列赋值进行比较。

如果您的第二个示例在a上使用了mutator方法:

a = 'b'
# => 'b'
d = a
# => 'b'
a[0] = 'c' # String#[]= alters its receiver
# => 'c'
d
# => 'c'

然后ad都会发生变化,因为您没有执行任务来更改a引用的对象,您正在更改引用的对象

这个问题并不是Is Ruby pass by reference or by value?的重复,但很接近但并不完整。我确定这是其他几个问题的重复,但我现在无法找到它们。如果有人发现了正确的副本,请告诉我,我会删除它并拔出我的笨锤。

答案 1 :(得分:1)

与原语不同,两个变量都指向同一个底层对象。如果您需要副本,可以使用克隆或复制。