On 20/12/11 08:48, Nick Sandberg wrote:
> I was working a project Euler problem and noticed that when I used this
> code:
>
> array1 = ["a", "b", "c", "d", "e"]
> array2 = Array.new
> array2<<  array1
> array1.clear
> p array2
>
> [[]] is my output. But, when I tried:
>
> array1 = ["a", "b", "c", "d", "e"]
> array2 = Array.new
> array2<<  array1
> array1 = []
> p array2
>
> [["a", "b", "c", "d", "e"]] is my output.  I am not understanding why
> clearing array1 is changing array2, but replacing the value of array1 is
> having no effect.
>
> (btw, using ruby 1.9.2p180)
>
So what is happening can be seen by inspecting object ids. In the first 
instance we create two new arrays which are referenced by variables 
array1 and array2 respectively.

1.9.2p290 :001 > array1 = ["a", "b", "c", "d", "e"]
  => ["a", "b", "c", "d", "e"]
1.9.2p290 :002 > array1.object_id
  => 4320500
1.9.2p290 :003 > array2 = Array.new
  => []
1.9.2p290 :004 > array2.object_id
  => 4205400

We then add the array which is referenced by array1 as the first element 
of array2

1.9.2p290 :005 > array2 << array1
  => [["a", "b", "c", "d", "e"]]
1.9.2p290 :006 > array2.first.object_id == array1.object_id
  => true

So in fact array2 now contains a reference to array1. This then does 
what we expect when the array referenced by array1 is cleared. You will 
notice the object reference remains the same.

1.9.2p290 :007 > array1.clear
  => []
1.9.2p290 :008 > array2
  => [[]]
1.9.2p290 :009 > array2.first.object_id == array1.object_id
  => true

Now what happens if we do the same thing, except instead of clearing the 
array referenced by array1, we assign a new array to array1.

  1.9.2p290 :010 > array1 = ["a", "b", "c", "d", "e"]
  => ["a", "b", "c", "d", "e"]
1.9.2p290 :011 > array1.object_id
  => 5232600
1.9.2p290 :012 > array2 = Array.new
  => []
1.9.2p290 :013 > array2.object_id
  => 5189800
1.9.2p290 :014 > array2 << array1
  => [["a", "b", "c", "d", "e"]]
1.9.2p290 :015 > array2.first.object_id == array1.object_id
  => true
1.9.2p290 :016 > array1 = Array.new
  => []
1.9.2p290 :017 > array2.first.object_id == array1.object_id
  => false
1.9.2p290 :018 > array2
  => [["a", "b", "c", "d", "e"]]

As you can see here, when array1 is told to reference a new array, the 
array it used to reference is still intact and remains in existence due 
to array2 still holding a reference to it. The variable array1 now 
points to a shiny new array and thus methods called via array1 are no 
longer received by the one we shoved into array2.

1.9.2p290 :019 > array1.object_id
  => 5144400
1.9.2p290 :020 > array2.object_id
  => 5189800
1.9.2p290 :021 > array2.first.object_id
  => 5232600

Does that help?

Sam