Переназначенный хеш изменяет исходный хеш - PullRequest
2 голосов
/ 14 июня 2019

Почему меняется переменная a и как ее предотвратить?

a = []       # => []
b = a        # => []
b << :hello  # => [:hello]
p a          # => [:hello]

# >> [:hello]

Я вижу ответы на использование клона, и мне интересно, почему ниже работает и в каких ситуациях .clone необходим и не нужен

a = "string"   # => "string"
b =a           # => "string"
b = "changed"  # => "changed"
a              # => "string"

Ответы [ 3 ]

2 голосов
/ 14 июня 2019

Почему переменная a изменяется и как ее предотвратить?

a = []       # => []
b = a        # => []
b << :hello  # => [:hello]
p a          # => [:hello]
# >> [:hello]

Переменная a равна , а не получениюизменилось.Единственный способ , который можно изменить, - присвоить ей (игнорируя отражение, как Binding#local_variable_set), чего вы не делаете.Следовательно, a не изменяется.

Объект , на который ссылается на и a и b, изменяется,Но изменение объекта и изменение переменной - это две совершенно разные вещи.

Я вижу ответы на использование клона, и мне интересно, почему ниже работает ив каких ситуациях .clone необходим и не нужен

a = "string"   # => "string"
b =a           # => "string"
b = "changed"  # => "changed"
a              # => "string"

Это работает, потому что вы никогда не меняете объект.Вы меняете переменную.

1 голос
/ 14 июня 2019

Почему вы используете мутирующий метод для массива и повторное связывание для строки и по-прежнему ожидаете, что они будут вести себя аналогично ?

a = "string"   #⇒ "string"
b = a          #⇒ "string"
b << "changed" #⇒ "stringchanged"
a              #⇒ "stringchanged"
0 голосов
/ 14 июня 2019

Как я понимаю, это из-за использования памяти.

Когда вы инициализируете объект, Ruby сначала инициализирует объект в памяти. Затем переменная указывает на этот адрес памяти. Когда вы назначаете эту переменную другой, она будет также указывать на этот адрес

Например,

a = []
a.object_id # 70220203482480
b = a
b.object_id # 70220203482480

Когда вы добавляете новый элемент, это означает, что вы добавляете значение в массив, который инициализирован в памяти, вызовы a и b оба покажут этот массив с новым элементом.

a.push(1)
b # [1]

Давайте посмотрим на второй пример

c = 'reference'
d = c
c.object_id #70220203442960
d.object_id #70220203442960

c.capitalize! # 'Reference'
d # 'Reference'

Если вы назначите d = 'new object', Ruby создаст другой объект в памяти и присвоит ему значение в виде строки new object, а затем d будет указывать на этот новый адрес памяти

d = 'new object'
d.object_id # 70220203334840 (different one)
c # 'Reference' (cause c still point to the last object in memory)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...