При вызове z = [...]
вы создаете новый экземпляр Array в памяти и сохраняете ссылку на него в локальной переменной z.
z = ['foo']
b = z
y = ['foo']
z.object_id # => 70314403278880
b.object_id # => 70314403278880 (same object)
y.object_id # => 70314411394940 (a different object)
При вызове arr(z)
фактически вы передаете методу ссылку на экземпляр массива, а не сам массив или указатель на локальную переменную.
Поскольку ссылка указывает на массив, вы можете что-то с ним делать, например добавлять элементы. То же самое касается строк и других «непостоянных» объектов. Вы не можете изменить номер.
Когда вы вызываете x = 10
, вы присваиваете идентификатор объекта 10
(обычно 21
) локальной переменной x
.
x = 10
y = x
z = 10
x.object_id # => 21
y.object_id # => 21
z.object_id # => 21
Когда вы звоните num(x)
, вы на самом деле звоните num(x.object_id)
. Локальная переменная метода n
используется для хранения ссылки, но метод никогда не получает ссылку на локальную переменную x
, которую вы использовали, x
больше не будет локальной переменной в этом случае.
Когда метод n += 10
меняет то, на что указывает n
, а не то, на что x
указывает.
Итак, в некотором смысле, ваш пример "пытается" сделать это 10 = 10 + 10
. После этого значение 10
будет равно 20 вперед и теперь 10 + 1
вернет 21
.
Другие объекты, которые ведут себя подобным образом, включают, например, true
, false
, :symbols
.