Changing one array in an array of arrays changes t

2019-12-16 19:39发布

问题:

a = Array.new(3,[])
a[1][0] = 5
a => [[5], [5], [5]]

I thought this doesn't make sense! isn't it should a => [[], [5], []] or this's sort of Ruby's feature ?

回答1:

Use this instead:

a = Array.new(3){ [] }

With your code the same object is used for the value of each entry; once you mutate one of the references you see all others change. With the above you instead invoke the block each time a new value is needed, which returns a new array each time.


This is similar in nature to the new user question about why the following does not work as expected:

str.gsub /(<([a-z]+)>/, "-->#{$1}<--"

In the above, string interpolation occurs before the gsub method is ever called, so it cannot use the then-current value of $1 in your string. Similarly, in your question you create an object and pass it to Array.new before Ruby starts creating array slots. Yes, the runtime could call dup on the item by default…but that would be potentially disastrous and slow. Hence you get the block form to determine on your own how to create the initial values.



标签: ruby arrays