Suprise in Ruby

I can not remember having read about it before, however the following
happens here:

irb(main):015:0> arr = Array.new(3, Array.new)
[[], [], []]
irb(main):016:0> arr[0].push(1)
[1]
irb(main):017:0> arr
[[1], [1], [1]]

ruby 1.8.5

but
irb(main):018:0> arr1 = Array.new(3)
[nil, nil, nil]
irb(main):019:0> 0.upto(2) {|i| arr1[i] = Array.new}
0
irb(main):020:0> arr1
[[], [], []]
irb(main):021:0> arr1[0].push(1)
[1]
irb(main):022:0> arr1
[[1], [], []]

I'm not getting it. Is it supposed to work that way?

Regards
Friedrich

···

--
Please remove just-for-news- to reply via e-mail.

Friedrich Dominicus <just-for-news-frido@q-software-solutions.de>
writes:

irb(main):015:0> arr = Array.new(3, Array.new)
[, , ]
irb(main):016:0> arr[0].push(1)
[1]
irb(main):017:0> arr
[[1], [1], [1]]

irb(main):018:0> arr1 = Array.new(3)
[nil, nil, nil]
irb(main):019:0> 0.upto(2) {|i| arr1[i] = Array.new}
0
irb(main):020:0> arr1
[, , ]
irb(main):021:0> arr1[0].push(1)
[1]
irb(main):022:0> arr1
[[1], , ]

I'm not getting it. Is it supposed to work that way?

I think so... see ri Array.new

In your first test, all array items refer to the same
default obj. If it happens to be modified, this modification affects all the
element that refer to this default object.

In you second test, the block create a new copy for each
element. Modifying one of them, doesn't affect the others.

···

--

I can not remember having read about it before, however the following
happens here:

irb(main):015:0> arr = Array.new(3, Array.new)

[...]

irb(main):018:0> arr1 = Array.new(3)
[nil, nil, nil]
irb(main):019:0> 0.upto(2) {|i| arr1[i] = Array.new}
0

[...]

I'm not getting it. Is it supposed to work that way?

Yes. In your first call, 'Array.new' is evaluated ONCE before the call, and hence all array members get initialised to use the SAME array.

In your second example, you call Array.new once per array index, to make sure every array index gets its own array assigned to it.

There is a slightly simpler way to achieve your desired behaviour, though:

   irb(main):004:0> arr=Array.new(3) { Array.new }
   => [, , ]
   irb(main):005:0> arr[0].push(1)
   => [1]
   irb(main):006:0> arr
   => [[1], , ]

In this case, you'd be passing in Array.new as a block - which gets evaluated ONCE per value in the array you're creating...

To make it a bit more apparent, see the difference between:

   irb(main):011:0> i=0
   => 0
   irb(main):012:0> Array.new(3,i+=1) # i+=1 gets evaluated ONCE
   => [1, 1, 1]

and

   irb(main):013:0> i=0
   => 0
   irb(main):014:0> Array.new(3) { i+=1 } # i+=1 gets evaluated once PER array item
   => [1, 2, 3]

The difference simply being that in the first case, your initialiser gets evaluated just once immediately before calling Array.new; and in the second case, Array.new calls your block once PER array item that gets created...

Benedikt

   ALLIANCE, n. In international politics, the union of two thieves who
     have their hands so deeply inserted in each other's pockets that
     they cannot separately plunder a third.
       (Ambrose Bierce, The Devil's Dictionary)

···

On Thu, 9 Nov 2006, Friedrich Dominicus wrote:

Hi --

···

On Thu, 9 Nov 2006, Friedrich Dominicus wrote:

I can not remember having read about it before, however the following
happens here:

irb(main):015:0> arr = Array.new(3, Array.new)
[, , ]
irb(main):016:0> arr[0].push(1)
[1]
irb(main):017:0> arr
[[1], [1], [1]]

ruby 1.8.5

but
irb(main):018:0> arr1 = Array.new(3)
[nil, nil, nil]
irb(main):019:0> 0.upto(2) {|i| arr1[i] = Array.new}
0
irb(main):020:0> arr1
[, , ]
irb(main):021:0> arr1[0].push(1)
[1]
irb(main):022:0> arr1
[[1], , ]

I'm not getting it. Is it supposed to work that way?

Yes. When you do this:

   Array.new(n, obj)

you get an array of size n, with each element initialized to obj. obj
is only evaluated once, so if it's "Array.new", you get the same array
for all the elements.

David

--
                   David A. Black | dblack@wobblini.net
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org

Benedikt Heinen <ruby@ml.icemark.net> writes:

···

On Thu, 9 Nov 2006, Friedrich Dominicus wrote:

I can not remember having read about it before, however the following
happens here:

irb(main):015:0> arr = Array.new(3, Array.new)

[...]

irb(main):018:0> arr1 = Array.new(3)
[nil, nil, nil]
irb(main):019:0> 0.upto(2) {|i| arr1[i] = Array.new}
0

[...]

I'm not getting it. Is it supposed to work that way?

Yes. In your first call, 'Array.new' is evaluated ONCE before the call,
and hence all array members get initialised to use the SAME array.

Yeah it has come to me this night that it's supposed to be right.

Anyway thanks for taking the time to answer

Regards
Friedrich

--
Please remove just-for-news- to reply via e-mail.