That is because when you clone
, you are creating a new instance of an array @board
, but its elements, which are also arrays, are not being replaced with new instances. You are not going deeply enough to clone the end elements. You need to do deep clone. You might want to look at some answers and gems suggested here or here.
An array shared despite cloning
Question
I have a class like this:
class Tiles
attr_accessor :board
def initialize
@board = Array.new(4) { Array.new(4) { 0 } }
end
...
Later, I call this method:
def display_board
padded_board = @board.clone
padded_board.each_with_index do |row, x|
row.each_with_index do |item, y|
padded_board[x][y] = pad_number(item)
end
puts row.join ' '
end
end
Anytime I change padded_board
, @board
gets changed as well. I can't figure out why this is happening. Any ideas?
Solution
OTHER TIPS
The reason is that array is in fact a set of pointers to other objects, in your case those objects are another arrays. When you are cloning array, you are creating new pointers, which points to the same objects. By calling padded_board[x][y]=
you are modifying the padded_board[x]
array, which is referenced by both @board
and padded_board
.
To fix it, you need to duplicate not only the array, but also each element of this array. Int his case this should be sufficient:
padded_board = @board.map(&:clone)
In more general case it is useful to extend Array with deep_dup
method. Rails have this method defined within ActiveSupport module, whcih can also be used in any non-rails project by adding `require 'active_support/core_ext/object/deep_dup'.