Array funkiness?

When trying to append to an array that lives in an array, it appends
to all until the individual array is used with =

Here’s exactly what I did

irb(main):007:0> a=Array.new(9,Array.new())
I expect and I get [[], [], [], [], [], [], [], [], []]

irb(main):008:0> a[0]<<1
I expect [[1], [], [], [], [], [], [], [], []]
but I get [[1], [1], [1], [1], [1], [1], [1], [1], [1]]

irb(main):009:0> a[0]<<1
I expect [[1,1], [], [], [], [], [], [], [], []]
but I get [[1, 1], [1, 1], [1, 1], [1, 1], [1, 1], [1, 1], [1, 1], [1,
1], [1, 1]]

irb(main):010:0> a[0]=[1,2,3]
I expect [[1,2,3], [], [], [], [], [], [], [], []]
but I get [[1,2,3], [1, 1], [1, 1], [1, 1], [1, 1], [1, 1], [1, 1],
[1, 1], [1, 1]]

So once more
irb(main):011:0> a[0]<<1
originally I would have expected
I expect [[1,2,3,1], [], [], [], [], [], [], [], []]
now because of this wacky behavior I expect
[[1, 2, 3, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1],
[1, 1,1], [1, 1, 1], [1, 1, 1]]
but what actually happens? This
[[1, 2, 3, 1], [1, 1], [1, 1], [1, 1], [1, 1], [1, 1], [1, 1], [1, 1],
[1, 1]]

What on earth is happening?

–Kyle

PS: I do have a work around so my code works as I expected it, using
+=[i] instead of <<i, but I really want to know why here.

Ahh. Any clue as to what the rational on making Array.new work that was
was?
I can think of situations where I’d want to use the same object over
and over, but more situations where I’d want a new object in each one.

Thanks alot!
–Kyle

On Feb 16, 12:01 pm, “Kyle S.” [email protected] wrote:

but I get [[1], [1], [1], [1], [1], [1], [1], [1], [1]]
The short answer is “RTFM” - type in
ri Array.new
in your console and you’ll see all this described.

The nice longer answer follows.

You basically asked Ruby to do:
b = Array.new
a = [b,b,b,b,b,b,b,b,b]
so modifying any particular instance modifies them all.

What you wanted was:
irb(main):001:0> a = Array.new(9){ Array.new }
=> [[], [], [], [], [], [], [], [], []]
irb(main):002:0> a[0] << 1
=> [1]
irb(main):003:0> a
=> [[1], [], [], [], [], [], [], [], []]

Kyle S. wrote:

When trying to append to an array that lives in an array, it appends
to all until the individual array is used with =

Here’s exactly what I did

irb(main):007:0> a=Array.new(9,Array.new())
I expect and I get [[], [], [], [], [], [], [], [], []]

You probably also expect those nine arrows to be nine different empty
arrays
(the result of calling Array.new nine times), but that is not the case.
Array.new is called exactly once and a[0] to a[8] point to the empty
array
resulting from that.
So naturally if you change one of the arrays, you change them all,
because
they’re all the same array.
If you however replace one of the arrays with another array, the rest
aren’t
affected.
I hope I explained this right and helped you understand.

On 2/16/07, Kyle S. [email protected] wrote:

Ahh. Any clue as to what the rational on making Array.new work that was was?
I can think of situations where I’d want to use the same object over
and over, but more situations where I’d want a new object in each one.

Yes.

bitvector = Array.new(32, 0)

If you need complex handling, as others have pointed out, use the block
form.

-austin

“Kyle S.” [email protected] wrote in message
news:[email protected]

Ahh. Any clue as to what the rational on making Array.new work that was
was?
I can think of situations where I’d want to use the same object over
and over, but more situations where I’d want a new object in each one.

Yes, because the other way isn't really possible.  Think about it.

You’re asking the array class to take the second parameter and… do
what
with it, exactly? Call the .dup method on it? That requires you to
needlessly assume the object has defined that method, an assumption we’d
rather not make if we didn’t have to…
The way it is now, it’s very natural to use the second parameter to
reference that object multiple times. Furthermore, the block naturally
performs whatever code that block does for each element, like iterators.
Thus, duplication is natural…
If you read the manual, you’ll see that this really is the better
interface…

On 2/17/07, Phrogz [email protected] wrote:

You basically asked Ruby to do:
b = Array.new
a = [b,b,b,b,b,b,b,b,b]
so modifying any particular instance modifies them all.

And the reason a[0] += [i] works is that internally it gets converted
to a[0] = a[0] + i, so that it returns a different object altogether.

martin