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.

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], , , , , , , , ]

···

On Feb 16, 12:01 pm, "Kyle Schmitt" <kyleaschm...@gmail.com> 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 [, , , , , , , , ]

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

Kyle Schmitt 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.

···

--
NP: Kreator - Carrion
Ist so, weil ist so
Bleibt so, weil war so

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

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

···

On 2/17/07, Phrogz <gavin@refinery.com> 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.

Yes.

  bitvector = Array.new(32, 0)

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

-austin

···

On 2/16/07, Kyle Schmitt <kyleaschmitt@gmail.com> 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.

--
Austin Ziegler * halostatue@gmail.com * http://www.halostatue.ca/
               * austin@halostatue.ca * You are in a maze of twisty little passages, all alike. // halo • statue
               * austin@zieglers.ca

"Kyle Schmitt" <kyleaschmitt@gmail.com> wrote in message
news:2b548b8b0702161129o28b8f31bg1c38e01b7a79d089@mail.gmail.com...

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...