Исходная переменная все еще изменяется с .clone или .dup

#ruby

#ruby

Вопрос:

Когда я выполняю эту программу, список original_couples и список new_couples всегда одинаковы. Я думал, что использование .clone или .dup должно было быть способом копирования без внесения изменений в исходную переменную. Так почему же это происходит здесь?

 def swingers(couples)

    original_couples = couples

    new_couples = original_couples.clone

    swap_index1 = rand(3)
    swap_index2 = rand(3)

    new_couples[swap_index1][0], new_couples[swap_index2][0] = new_couples[swap_index2]    [0], new_couples[swap_index1][0] 

    puts original_couples
    puts new_couples
end
swingers([
  ["Clyde", "Bonnie"],
  ["Paris", "Helen"],
  ["Romeo", "Juliet"]
])  
 

Ответ №1:

dup Или clone в Ruby — это неглубокий клон, означающий, что клонируется только внешний объект, а не его дочерние элементы. В вашем случае это означает, что couples массив копируется, но не каждая отдельная пара.

Если вы хотите, чтобы это был глубокий клон, вам нужно сделать это вручную для массивов stdlib:

 new_couples = original_couples.map { |couple| couple.clone }
 

Если вы находитесь в домене, где часто требуются копии коллекций, или вы пытаетесь работать в более функциональном стиле, я предлагаю вам взглянуть на Hamster gem, который переносит неизменяемые структуры данных в ruby.