Используйте это вместо:
a = Array.new(3){ [] }
В вашем коде один и тот же объект используется для значения каждой записи;как только вы мутируете одну из ссылок, вы видите, что все остальные меняютсяС учетом вышеизложенного вы вместо этого вызываете блок каждый раз, когда требуется новое значение, которое возвращает новый массив каждый раз .
Это по своей природе похоже на новоевопрос пользователя о том, почему следующее не работает должным образом:
str.gsub /(<([a-z]+)>/, "-->#{$1}<--"
В приведенном выше примере интерполяция строк происходит до того, как метод gsub
когда-либо вызывается, поэтому он не может использоватьтекущее значение $1
в вашей строке.Аналогично, в вашем вопросе вы создаете объект и передаете его Array.new
до того, как Ruby начнет создавать слоты массивов.Да, среда выполнения может вызывать dup
для элемента по умолчанию ... но это может быть пагубным и медленным.Следовательно, вы получаете блочную форму, чтобы самостоятельно определить, как создавать начальные значения.