5

When i write the following code:

x= [1,2,3]
x << x
puts x
puts x[3]
puts x[3][3][3][3][3][3][3][3][3][3]

I get this output:

[1, 2, 3, [...]]
[1, 2, 3, [...]]
[1, 2, 3, [...]]

Shouldn't I get only [1,2,3,[1,2,3]] and what would be the explanation?

2 Answers 2

10

There's nothing strange about this. The fourth element of the array is the array itself, so when you ask for the fourth element, you get the array, and when you ask for the fourth element of the fourth element, you get the array, and when you ask for the fourth element of the fourth element of the fourth element of the fourth element ... you get the array.

Simple as that.

The only slightly unusual thing is that Array#to_s detects such recursion and instead of going into an infinite loop, returns an ellipsis.

Sign up to request clarification or add additional context in comments.

5 Comments

In Ruby 1.9, Array#<=>, #eql? and #hash also deal with recursion, same for Hash and Struct... Not sure why you consider it "unusual"! blog.marc-andre.ca/2009/05/lost-in-recursion.html
I don't think "infinitely recursive self-referential array" is a typical use case that the normal programmer would consider :-) I've written my share of to_s implementations, but I never considered special casing for that. If someone asks for a string representation of an infinite data structure, they'll get an infinite loop. Period. I mean, map for an infinite Enumerator returns an infinitely large array, and nobody thinks twice about that, isn't that somewhat the same?
I think it's nice that Ruby deals with recursive structures nicely. I'm not sure they are so unusual, e.g. structures that hold their parent & children. If that wasn't the case, ref counting would be all that's needed to handle memory :-)
Oh, another case where they're handled properly: YAML & Marshal dumps/loads.
I consider it unusual because i think i should have get [1,2,3,[1,2,3]]. Do you have other examples of this?
7

When you write x << x you are appending to x with a reference to itself, creating a recursive/infinite array.

Compare this with x << x.dup which appends a copy of x onto x. This is equal to [1,2,3,[1,2,3]]

2 Comments

yes that's right, but shouldn't it be the same if I was writing x+=x ? I mean to create an other kind of recursive array.
x+=x is equivalent to x = x + x, which means create a new array by joining the elements from x with the elements from x and then make x refer to this newly created array so you end up with [1, 2, 3, 1, 2, 3]. << pushes the given object onto the end of an array (no new array is created.) See the docs for + and docs for <<.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.