Я правильно понимаю?
Да, я считаю, что это так. Я повторяю то, что говорит Макс, и также немного уточню на случай, если это поможет.
Каждый b
- это вновь созданный объект, потому что он создается внутри блока, поэтому он воссоздается с каждой новой итерацией . a
создается вне блока, поэтому один и тот же объект (a
) продолжает получать ссылки внутри блока для каждой итерации.
Вы можете лучше понять, как это работает, поэкспериментировав с #object_id
. Попробуйте запустить этот код:
a="123456789"
t=[[1,4],[3,4],[4,5],[1,2]]
p t.map { |x,y|
b = "#{a}" # IMPORTANT - this builds a new string
b[x],b[y]=b[y],b[x]
p "a.object_id = #{a.object_id}"
p "b.object_id = #{b.object_id}"
b
}
Вы заметите, что a
- это один и тот же объект для каждой итерации метода #map
, а b
- новый.
Это пример концепции закрытия . Замыкание - это своего рода закрытая структура кода, которая сохраняет доступ к любому состоянию, доступному в контексте, в котором оно было создано, в то время как этот контекст не имеет доступа к своему состоянию закрытого кода. Что-то вроде «одностороннего зеркала»: закрытый код может видеть снаружи, но снаружи не может видеть закрытый код.
В Ruby замыкания реализованы как блоки: блоки являются замыканиями. Таким образом, все, что видно для любого контекста, в котором создан блок (в данном случае main
), также видно для этого блока, хотя обратное неверно - например, вы не можете ссылаться на b
извне. блок. (Методы не являются закрытием: если бы ваш блок был методом, он не смог бы увидеть a
, если бы вы не передали его в качестве аргумента вашему методу.)
Итак, как говорит Макс, когда вы вносите изменения в a
внутри своего блока, вы фактически меняете (мутируете) тот же a
, который вы определили вверху каждый раз.
Side topi c
Теперь, если вы ссылаетесь на отдельные символы в строках, важно понимать, что основная структура строк отличается от структуры массивов. Кроме того, массивы ведут себя по-разному, когда вы изменяете их элементы из строк, когда вы мутируете их символы. Ссылки. Это в значительной степени верно только в отношении синтаксиса.
Результаты выполнения этого кода могут показаться интересными:
a = '123456789'
p a.object_id
p a[0].object_id
p a[1].object_id
a[0] = '7'
p a.object_id
p a[0].object_id
p a[1].object_id
puts
a = '123456789'.chars
p a.object_id
p a[0].object_id
p a[1].object_id
a[0] = '7'
p a.object_id
p a[0].object_id
p a[1].object_id
В частности, сравнение четырех выходных данных a[1].object_id
должен быть поучительным, потому что он показывает, где строки и массивы отличаются. Если вы переназначаете элемент в массиве, этот элемент и только этот элемент получает новый идентификатор объекта. Если вы переназначаете символ в строке, сам строковый объект остается прежним, но каждый символ в строке создается заново.