The first thing that really surprised me today was the flexibility of Ruby's shovel operator, <<
. A student in the class had tried the following:
a = [0]
a << a
What do you think a
is now? I was sure it would be [0, [0]]
. But lo and behold, Ruby sparkles;
a = [0]
a << a
=> [0, [...]]
Whoa... [...]
? What is that? Let's try this;
a[1]
=> [0, [...]]
...Huh. It seems that a[1] == a
. The second entry in the array is the same thing as the array. How is that possible? It's only possible if a
is infinite.
How does Ruby handle this? Here's my guess.
First let's consider the difference between reference and value. A reference is something that refers to something else. A reference can refer to another reference, or it can refer to a value. All variables are references; they refer to some value somewhere (or they refer to a reference which refers to a value eventually...). A value is a literal. So a value will be a number, or a string, or an array, et cetera. When we write a = [0]
, we tell the computer to make the variable a
refer to the value [0]
. When we write b = a
, we tell the computer to make the variable b
refer to whatever a
eventually refers to--in this case [0]
.
Based on the behavior above, the shovel operator a << b
must say, "make a new last entry of a
and make that last entry refer to whatever b
refers to." The alternative I expected was, "...make that last entry refer to the value of what b
refers to."
So in the case of our infinite array, the second element a[1]
is a reference to a
itself. Normally this would be a problem in a programming languages. Ruby must have some kind of self-reference detection that converts these into meaningful objects.
Good stuff