4

What is the difference between these two assignments? Why do they have different results?

arr3 = Array.new(2, Array.new(2, 0))
arr4 = [[0, 0], [0, 0]]

arr3 == arr4  # => true
arr3 === arr4  # => true

arr3[0][0] = "/"
arr4[0][0] = "/"

arr3  # => [["/", 0], ["/", 0]]
arr4  # => [["/", 0], [0, 0]]
sawa
  • 165,429
  • 45
  • 277
  • 381

2 Answers2

5

Because arr3 contains two identical objects, but arr4 contains two different objects.

>> arr3 = Array.new(2, Array.new(2, 0))
=> [[0, 0], [0, 0]]
>> arr3.map { |ary| ary.object_id }
=> [73703490, 73703490]
>> arr4 = [[0, 0], [0, 0]]
=> [[0, 0], [0, 0]]
>> arr4.map { |ary| ary.object_id }
=> [73670930, 73670920]
>>

Read new(size=0, default=nil)

...In the first form, if no arguments are sent, the new array will be empty. When a size and an optional default are sent, an array is created with size copies of default. Take notice that all elements will reference the same object default.

You created arr3 using the form above, while creating arr4 using the literal constructor [].

A new array can be created by using the literal constructor []. Arrays can contain different types of objects.

If you want Array::new to behave as literal construct, then go with new(size) {|index| block } form.

>> arr3 = Array.new(2){ Array.new(2, 0) }
=> [[0, 0], [0, 0]]
>> arr3.map { |ary| ary.object_id }
=> [73551460, 73551450]
>>
Arup Rakshit
  • 116,827
  • 30
  • 260
  • 317
-2

Two elements in arr3 share the same object_id, so they will be changed together.

CODE:

arr3.each do |item|
  p item.object_id
end

arr4.each do |item|
  p item.object_id
end

But I still don't know why Array.new made this happen.

sawa
  • 165,429
  • 45
  • 277
  • 381