Сумасшедшее поведение (по крайней мере для меня) при установке одной строки на другую в Ruby - PullRequest
0 голосов
/ 05 февраля 2011

Как новичок, я, наверное, что-то упустил в Ruby, но я не понимаю этого результата. Итак, у меня есть эта простая функция:

def crazyfunc(s)
  s.gsub!('a', 'b')
  #return has not purpose here
end

Теперь у меня есть несколько простых комплектов.

s1 = 'abc'
s2 = s1
s2 = crazyfunc(str2)

puts s1

=> bbc

Почему в мире s1 подвержен влиянию crazyfunc? Так что вместо этого:

def crazyfunc(s)
  return s.gsub('a', 'b')
end

не меняет str1, поэтому я думаю, что это связано с тем, что делает gsub на месте. Но я до сих пор не понимаю, почему str1 будет изменен.

Ответы [ 3 ]

5 голосов
/ 05 февраля 2011

Присвоение строки в Ruby не копирует строку неявным образом. Вы просто назначаете другую ссылку на него. Если вы хотите скопировать строку, используйте clone.

Для демонстрации вы можете проверить идентификаторы объектов:

ree-1.8.7-2010.02 > a = "foo"
 => "foo"
ree-1.8.7-2010.02 > b = a
 => "foo"
ree-1.8.7-2010.02 > a.object_id
 => 81728090
ree-1.8.7-2010.02 > b.object_id
 => 81728090

Поскольку a и b имеют одинаковый идентификатор объекта, вы знаете, что это один и тот же объект. Если вы хотите изменить b как копию a, вы можете использовать методы, которые возвращают новую строку (например, gsub вместо gsub!), или вы можете использовать b = a.clone, а затем работать b.

ree-1.8.7-2010.02 > a = "foo"
 => "foo"
ree-1.8.7-2010.02 > b = a.clone
 => "foo"
ree-1.8.7-2010.02 > a.object_id
 => 81703030
ree-1.8.7-2010.02 > b.object_id
 => 81696040
ree-1.8.7-2010.02 > b.gsub! "f", "e"
 => "eoo"
ree-1.8.7-2010.02 > a
 => "foo"
ree-1.8.7-2010.02 > b
 => "eoo"

Или проще:

ree-1.8.7-2010.02 > a = "foo"
 => "foo"
ree-1.8.7-2010.02 > b = a.gsub("f", "e")
 => "eoo"
ree-1.8.7-2010.02 > puts a, b
foo
eoo
0 голосов
/ 05 февраля 2011
s1 = 'abc'
s2 = s1
s2 = crazyfunc(str2)

A #master

B = A

C = B

A - это A, а B равно A, а C равно B. Если вы измените B, это не повлияет на A, но повлияет на C. Посмотрите, как оно каскадно падает. Переменные, которые вы перечисляете, являются просто указателями.

Итак, у вас есть только одна главная переменная, и вам нужно объявить две.

0 голосов
/ 05 февраля 2011

Вы сталкиваетесь с тем, что все в Ruby является объектом, а переменные являются просто ссылками на объекты.

Когда вы присваиваете str1 = str2, вы фактически указываете на один и тот же объект.Когда вы затем изменяете объект, на который указывает str2, вы также изменяете объект, на который указывает str1.

В вашем оригинальном crazyfunc вы модифицируете строку, возвращаете измененную строку, а затем меняете значениеобъект, на который указывают str2 - и str1, так как они указывают на один и тот же объект.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...