Reputation: 15471
If the following code is run in an IRB console:
arr = [[], 1]
arr[0]<<arr
The result is [[[...], 1]]
.
Thereafter arr[0]
, arr[0][0]
, arr[0][0][0]
, etc. produce the same output.
This sort of makes sense, because I can't display arbitrary amounts of nesting right?
However, arr[0][1]
produces nil (rather then 1
) what?
But arr[0][0][1]
prints 1
.
arr[0][0][0][1] => nil
then:
arr[0][0][0][0][1] => 1
etc.
What is going on? What is the structure that is actually created? How deep does this structure recurse? Where are the nils coming from?
Upvotes: 0
Views: 57
Reputation: 118271
Array#size
is the essential too to demonstrate why sometimes you are seeing nil
or 1
as the output:
arr = [[], 1]
arr[0]<< arr
arr.size # => 2
arr # => [[[...]], 1]
arr[0] # => [[[...], 1]]
arr[0].size # => 1
arr[0][1] # => nil
arr[0][0] # => [[[...]], 1]
arr[0][0].size # => 2
arr[0][0][1] # => 1
arr[0][0][0] # => [[[...], 1]]
arr[0][0][0].size # => 1
arr[0][0][0][1] # => nil
arr[0][0][0][0] # => [[[...]], 1]
arr[0][0][0][0].size # => 2
arr[0][0][0][0][1] # => 1
Upvotes: 1
Reputation: 15010
Just see what is inside
arr[0]
# => [[[...], 1]]
arr[0]
is an array that has only one element. So [1]
will be out of this array and return nil.
arr[0][0]
# => [[[...]], 1]
arr[0][0]
will get into the only one element of the top array and this element contains two values so [1]
will found a value.
It behaves so because you did arr[0] << arr
and not arr[0] = arr
.
By doing arr = [[], 1]; arr[0] << arr
you did not set arr
as arr[0]
but your added arr
as an element of arr[0] which is an array itself.
If you had done otherwise
arr = ["whatever", 1]
# => ["whatever", 1]
arr[0] = arr
# => [[...], 1]
arr[0][1]
# => 1
arr[0][0][1]
Edit
Back to your question, why does it become a recursive array. You are not passing arr
's value to arr[0]
but its reference.
arr = ["whatever", 1]
# => ["whatever", 1]
arr.object_id
# => 69999412942060
arr[0] = arr
# => [[...], 1]
arr[0].object_id
# => 69999412942060
arr[0].object_id == arr.object_id
# => true
You have Ouroboros right there since arr
and arr[0]
refers the same object.
If you wanted to only insert its value you should have deep_copied it first.
arr = ["whatever", 1]
arr_copy = Marshal.load(Marshal.dump(arr)) # copy the value,
# delete the object reference dependence
arr[0] = arr_copy
puts arr.inspect
# [["whatever", 1], 1] # no infinit recurrence.
Upvotes: 1