Ruby - Параметры по ссылке или по значению?

Я не понимаю, почему они говорят. Ruby передает все параметры по значению и в то же время следующий код доказывает обратное:

class MyClass1
  @var1 = 123

  def get1
    @var1
  end

  def set1=value
    @var1 = value
  end
end

c1 = MyClass1.new
c1.set1 = 444
p c1.get1 # 444

def test1 mc
  mc.set1 = 999
end

test1 c1
p c1.get1 # 999

Если бы он был по значению, он распечатывал 444, а не 999.

Ответ 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? Он передается по значению, но все значения являются ссылками.