[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Array funkiness?

Kyle Schmitt

2/16/2007 7:01:00 PM

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.

6 Answers

Gavin Kistner

2/16/2007 7:18:00 PM

0

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

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

Sebastian Hungerecker

2/16/2007 7:26:00 PM

0

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

Kyle Schmitt

2/16/2007 7:29:00 PM

0

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

Austin Ziegler

2/16/2007 7:53:00 PM

0

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.

Yes.

bitvector = Array.new(32, 0)

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

-austin
--
Austin Ziegler * halostatue@gmail.com * http://www.halo...
* austin@halostatue.ca * http://www.halo...feed/
* austin@zieglers.ca

Randy R

2/16/2007 11:46:00 PM

0


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



Martin DeMello

2/17/2007 11:12:00 AM

0

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.

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