# Suprise in Ruby

**URL:** <https://www.ruby-forum.com/t/suprise-in-ruby/75262>\
**Category:** Ruby\
**Created:** [November 8, 2006, 4:51pm UTC](https://www.ruby-forum.com/t/suprise-in-ruby/75262 "2006-11-08T16:51:39Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![friedrich](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/eb9ed0/32.png) [@friedrich](https://www.ruby-forum.com/u/friedrich)\
**Post date:** [November 8, 2006, 4:51pm UTC](https://www.ruby-forum.com/t/suprise-in-ruby/75262/1 "2006-11-08T16:51:39Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![friedrich](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/eb9ed0/32.png) [@friedrich](https://www.ruby-forum.com/u/friedrich)\
**Post date:** [November 8, 2006, 5:03pm UTC](https://www.ruby-forum.com/t/suprise-in-ruby/75262/2 "2006-11-08T17:03:41Z")

</div>

Friedrich D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
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]]

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

---

<div class="post-metadata">

**Author:** ![friedrich](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/eb9ed0/32.png) [@friedrich](https://www.ruby-forum.com/u/friedrich)\
**Post date:** [November 8, 2006, 5:05pm UTC](https://www.ruby-forum.com/t/suprise-in-ruby/75262/3 "2006-11-08T17:05:42Z")

</div>

On Thu, 9 Nov 2006, Friedrich D. 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.

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)

---

<div class="post-metadata">

**Author:** ![friedrich](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/eb9ed0/32.png) [@friedrich](https://www.ruby-forum.com/u/friedrich)\
**Post date:** [November 9, 2006, 4:45am UTC](https://www.ruby-forum.com/t/suprise-in-ruby/75262/4 "2006-11-09T04:45:29Z")

</div>

Benedikt H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:

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

---

<div class="post-metadata">

**Author:** ![friedrich](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/eb9ed0/32.png) [@friedrich](https://www.ruby-forum.com/u/friedrich)\
**Post date:** [November 8, 2006, 5:17pm UTC](https://www.ruby-forum.com/t/suprise-in-ruby/75262/5 "2006-11-08T17:17:43Z")

</div>

Hi –

On Thu, 9 Nov 2006, Friedrich D. wrote:

> ruby 1.8.5  
> 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
