What is wrong with this few lines of code

ar = Array.new( 2,[])
%w(a b).each do |e|
ar[0] << e
ar[1] << e
end
ar.each do |e|
e.each {|line| p line}
end

Returns
“a”
“a”
“b”
“b”
“a”
“a”
“b”
“b”

I would expect:
“a”
“b”
“a”
“b”

by
TheR

Hi Damjan

The code ar = Array.new(n, []) actually makes n copies of the same
object
(empty array), so each time you do either ar[0] << e or ar[1] << e you
are
appending elements to the same array.

What I guess you want is to different objects, and you can do that by
e.g.
ar = Array.new(2){[]}
(or just ar = [[],[]] …or many other ways :o) )

Best regards,
Rolf

At 2010-04-23 08:49AM, “Damjan R.” wrote:

ar = Array.new( 2,[])

ar[0] and ar[1] both refer to the same (empty) array at this point

ar = Array.new(2, [])  # => [[], []]
ar[0].object_id        # => 136474520
ar[1].object_id        # => 136474520

You want the block syntax for Array.new

ar = Array.new(2) {[]}  # => [[], []]
ar[0].object_id         # => 136514378
ar[1].object_id         # => 136514364

Hi,

Am 23.04.2010 14:49, schrieb Damjan R.:

Returns
“a”
“b”
“a”
“b”

works as expected with ruby 1.9.1p376 (2009-12-07 revision 26041)
[i386-cygwin].

Kind regards

Waldemar

2010/4/23 Rolf P. [email protected]:

The code ar = Array.new(n, []) actually makes n copies of the same object
(empty array), so each time you do either ar[0] << e or ar[1] << e you are
appending elements to the same array.

That description is inconsistent and might confuse one or the other
reader: there are no copies made of the object (Array in this case)
but only of the reference!

irb(main):001:0> a = Array.new(3,[])
=> [[], [], []]
irb(main):002:0> a.map {|x| x.object_id}
=> [135000124, 135000124, 135000124]
irb(main):003:0> a.map {|x| x.object_id}.uniq
=> [135000124]

The idiom you describe when you say “copy” is the block form of
Arra.new:

irb(main):004:0> a = Array.new(3) { [] }
=> [[], [], []]
irb(main):005:0> a.map {|x| x.object_id}
=> [135669212, 135669198, 135669184]
irb(main):006:0> a.map {|x| x.object_id}.uniq
=> [135669212, 135669198, 135669184]

What I guess you want is to different objects, and you can do that by e.g.
ar = Array.new(2){[]}
(or just ar = [[],[]] …or many other ways :o) )

Exactly.

Kind regards

robert

Hi –

On Fri, 23 Apr 2010, Waldemar Dick wrote:

e.each {|line| p line}
“b”

I would expect:
“a”
“b”
“a”
“b”

works as expected with ruby 1.9.1p376 (2009-12-07 revision 26041)
[i386-cygwin].

Are you saying that you’re getting the second result from exactly the
same code? (It should give the first result.)

David


David A. Black, Senior Developer, Cyrus Innovation Inc.

THE Ruby training with Black/Brown/McAnally
COMPLEAT Coming to Chicago area, June 18-19, 2010!
RUBYIST http://www.compleatrubyist.com

Hi,

Am 23.04.2010 16:47, schrieb David A. Black:
[…]

Are you saying that you’re getting the second result from exactly the
same code? (It should give the first result.)

sorry, I must have missed the second assignment (ar[1]<< e), so I got
the wrong result.

Waldemar