Ответ 1
Этот вопрос путает людей, потому что есть вещь, называемая ссылочным типом, и есть вещь, называемая pass-by-reference, но на самом деле у них нет ничего общего друг с другом.
Ссылки и значения и значения, которые являются ссылками: A (sorta) краткий обзор
В сценарии с пересылкой параметры функции являются ссылками на переменные, которые были переданы в функцию, а изменение параметров изменяет исходные переменные. Это не то, что Ruby. Например, рассмотрим следующий код:
def inc(val)
val += 1
end
a = 1
inc a
puts a
Если Ruby был языком с пересылкой, эта программа будет печатать 2, потому что val += 1
в inc
увеличит значение a
. Но это не то, что происходит. Переменная val
не является ссылкой на переменную a
- это независимая переменная, которой присваивается то же значение.
"Но подождите!" . "Что, если мы имеем дело с объектами? Несомненно, переменные объекта передаются по ссылке, правильно?"
Нет.
def change_string(str)
str << " I can insult you all you want"
str << " because you'll never see this"
str << " because I'm going to replace the whole string!"
str << " Haha you smell bad!"
str = "What? I didn't say anything." # I'm so sneaky
end
be_nice_to_me = "hello"
change_string(be_nice_to_me)
puts be_nice_to_me
Если Ruby был pass-by-reference, вы никогда не увидите, насколько средним является метод change_string
, потому что str = "What, I didn't say anything."
полностью заменит значение be_nice_to_me
на строку "What? I didn't say anything."
Но на самом деле change_string
Грехи обнажены для всех. Как это возможно, если Ruby не проходит по ссылке?
Хорошо, помните те ссылочные типы, о которых я говорил раньше? Ну, какие объекты находятся в Ruby. Тип ссылки - это тип, значение которого является ссылкой на что-то еще. В этом случае значение переменной является ссылкой на строку "hello"
. Когда вы передаете строку, значение переменной - которое является ссылкой - копируется в переменную str
. Итак, теперь они сохраняют ссылки на один и тот же объект, но str
не ссылается на be_nice_to_me
. Поэтому, когда вы изменяете объект, эти изменения появляются, потому что они оба относятся к одному и тому же объекту. Но когда вы изменяете одну переменную, другая не видит ее, потому что ни одна из переменных не является ссылкой на другую.
Итак, Ruby pass-by-reference или pass-by-value? Он передается по значению, но все значения являются ссылками.