Поведение хеш-слияния - PullRequest
       26

Поведение хеш-слияния

0 голосов
/ 03 февраля 2012

Правильно ли это поведение?Я запускаю некоторый код, подобный следующему:

@a_hash = {:a => 1}
x = @a_hash
x.merge!({:b => 2})

В конце всего этого значение x было изменено, как и ожидалось, но также изменилось значение для @a_hash.Я получаю {: a => 1,: b => 2} в качестве значения для них обоих.Это нормальное поведение в Ruby?

Ответы [ 3 ]

4 голосов
/ 03 февраля 2012

Да, переменная экземпляра @a_hash и локальная переменная x сохраняют ссылку на тот же экземпляр Hash и при изменении этого экземпляра (используя метод мутатора merge!, который изменяет объект на месте), эти переменные будут оценены в одно и то же значение.

Возможно, вы захотите использовать merge метод, который создает копию объекта и не меняет исходную:

@a_hash = {:a => 1}
x = @a_hash
y = x.merge({:b => 2})
# y => {:a => 1, :b => 2}
# x and @a_hash => {:a => 1}
3 голосов
/ 03 февраля 2012

@ a_hash - это ссылка на x. Поэтому, если вы хотите, чтобы @a_hash не изменился, вы должны сделать так:

@a_hash = {:a => 1}
x = @a_hash.clone
x.merge!({:b => 2})
1 голос
/ 03 февраля 2012

Да, это нормальное поведение в ruby ​​(и большинстве других языков).И x, и @a_hash являются ссылками на один и тот же объект.Вызывая merge!, вы изменяете этот объект и это изменение видимым через все переменные, которые к нему относятся.

Если вы не хотите такого поведения, вы не должны либо использовать методы мутации (то есть использовать x = x.merge(...)вместо этого) или скопируйте объект перед его изменением (т. е. x = @a_hash.dup).

...