1

In use Ruby 2.3, irb

a, b = [], [1,2,3]
3.times do
  b[0] += 1
  a << b
end

expected:

=> [[2, 2, 3], [3, 2, 3], [4, 2, 3]]

but I get

=> [[4, 2, 3], [4, 2, 3], [4, 2, 3]]

why? Thanks

P.S.

if I do

a = []
3.times do |n|
  a << n
end

I get right result a == [0,1,2]

Oleh Sobchuk
  • 3,612
  • 2
  • 25
  • 41

1 Answers1

4

You get the same because b is the same object which you are appending 3 times in a. b remains unchanged. That's why a stores the same values.

p a.map(&:object_id) # => three same object id referencing to b. 

Even if you do a[0][1] = 100, you will see the same value reflected in all positions => [[4, 100, 3], [4, 100, 3], [4, 100, 3]]

You should use Array#dup to save intermediate b values.

a, b = [], [1,2,3]
3.times do
  b[0] += 1
  a << b.dup
end
=> [[2, 2, 3], [3, 2, 3], [4, 2, 3]]

For latter part of you question you might want to read - Ruby - Parameters by reference or by value?

Community
  • 1
  • 1
kiddorails
  • 12,961
  • 2
  • 32
  • 41
  • Added link to explain latter part of the question. `n` is the different reference each time in that block. :) – kiddorails Aug 25 '16 at 22:00