0

Recently I was playing with arrays and found out a weird behavior. I created a new array using Array.new.

arr = Array.new(4,"happy")

["happy", "happy", "happy", "happy"]

I appended a word into the second element in that array like shown below

arr[1] <<" Dino"

When I looked at arr, I was expecting an array with the second element having an appended word. But to my surprise array returned with all elements with the appended word.

["happy Dino", "happy Dino", "happy Dino", "happy Dino"]

How can this happen? Are we creating copies of the same string when we are creating the array? It doesn't happen if we use arr[1]= " Dino". Somebody can explain why this is happening?

Shan
  • 613
  • 9
  • 21
  • I'm not seeing this behavior, `ar = ["happy", "happy", "happy", "happy"] ar[1] <<" Dino"`, the output is `happy happy Dino happy happy` – Bman70 May 29 '19 at 07:21
  • @Bman70 it won't happen when you do like that. Try using Array.new(size, string). When we declare and initialize an array with new. I am thinking the same string is getting copied to all elements, Which makes their object id same. – Shan May 29 '19 at 07:30
  • 1
    By gum, you're right. Strange. – Bman70 May 29 '19 at 07:37
  • 1
    Can you explain what *precisely* is unclear to you about the documentation of `Array::new`? That way, the Ruby developers can improve the documentation so that future developers don't fall into the same trap as you did. Please, help making the world a better place! – Jörg W Mittag May 29 '19 at 07:47
  • 1
    The documentation contains a [common gotchas](http://ruby-doc.org/core-2.6.3/Array.html#method-c-new-label-Common+gotchas) section explaining what's going on: _"the same object will be used as the value for all the array elements […] changes to one of them will affect them all"_ – Stefan May 29 '19 at 10:14

2 Answers2

3

Yes, you a right. See the ruby docs

When a size and an optional default are sent, an array is created with size copies of default. Take notice that all elements will reference the same object default.

You can initialize array in a way like this:

arr = Array.new(4){ 'happy' }
Peter Balaban
  • 653
  • 3
  • 7
2

When we take Array.new(4, "Happy") it will create 4 elements with same object id. We can observe in irb arr[1].object_id => 2880099 , arr[2].object_id => 2880099 and remaining 2 elements also will return same object id.

So when we try like arr[1] << "Something" , this string will append to all the same object id's.

Now if we take another element for arr like arr.push("newString"). Now if see the last element object id arr.last.object_id => 4889988,it's different now.

So if we try same command arr[1] << "Something" it won't be effect to newly inserted element because object id is different.

if you don't want this behaviour the use Array.new(4){ 'String' }

kishore cheruku
  • 511
  • 2
  • 11