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: