As mentioned in this answer, Array.new(size, object)
creates an array with size
references to the same object
.
hash = Hash.new
a = Array.new(2, hash)
a[0]['cat'] = 'feline'
a # => [{"cat"=>"feline"},{"cat"=>"feline"}]
a[1]['cat'] = 'Felix'
a # => [{"cat"=>"Felix"},{"cat"=>"Felix"}]
Why does Ruby do this, rather than doing a dup
or clone
of object
?
Each element in an array is associated with and referred to by an index. Array indexing starts at 0, as in C or Java. A negative index is assumed relative to the end of the array --- that is, an index of -1 indicates the last element of the array, -2 is the next to last element in the array, and so on.
Because that's what the documentation says it does. Note that Hash.new
is only being called once, so of course there's only one Hash
If you want to create a new object for every element in the array, pass a block to the Array.new
method, and that block will be called for each new element:
>> a = Array.new(2) { Hash.new }
=> [{}, {}]
>> a[0]['cat'] = 'feline'
=> "feline"
>> a
=> [{"cat"=>"feline"}, {}]
>> a[1]['cat'] = 'Felix'
=> "Felix"
>> a
=> [{"cat"=>"feline"}, {"cat"=>"Felix"}]
For certain classes that can't be modified in-place (like Fixnum
s) the Array.new(X, object)
form works as expected and is probably more efficient (it just calls memfill
instead of rb_ary_store
and yield
ing to the block):
For more complicated objects you always have the block form (e.g. Array.new(5) { Hash.new }
).
*Edit:* Modified according to the comments. Sorry for the stupid example, I was tired when I wrote that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With