Austin Z. wrote:
…
object. But if you move the sticky note, you’re changing the object to
which it references. Since they’re labels, the sticky notes don’t
contain anything – they just name the object that they’re attached to.
Since they don’t contain anything, no other sticky note can point to
another sticky note.
A Ruby variable is nothing like a C++ variable. Never has been, never
will be.
It’s not so mysterious. If you’re coming from C/C++, you may find it
helpful to think of a ruby variable as a C void* variable. Assigning
between variables in ruby is just like C assignment between two void*
vars.
In many cases, the void* points to a struct with the data of the object,
including some flags, a pointer to the class of the object, a pointer to
the table of instance variables, and so on. Assignment copies the void*
pointer (4 bytes), not the struct (20+ bytes).
In a few cases, the void* isn’t really a pointer, but an immediate
value: a fixnum, boolean, or symbol. In those cases, though, you can
just as well think of it as a pointer to a unique instance of the number
42, or whatever. At least, that’s a useful fiction when you’re writing
ruby code, but not when you’re writing an extension in C.
If you’re not coming from C/C++, the following metaphor (maybe a
variation on the sticky metaphor, but I like it better) may help:
On a piece of paper, draw a vertical line. On the left of the line,
write down some variable names:
x
y
z
On the right of the line, write down some values:
1
7.2
false
“hello, world”
[ [1, 0], [0, 1] ]
Now, draw some arrows from left to right, connecting names with values.
Make sure that each name has only one arrow coming out of it. (Those
arrows are together called a binding.) The things on the right have a
physical location in memory. The things on the left do too, but in a
more subtle way.
What the assignment “y = x” means is: look at the value that the arrow
from x leads to, then erase the arrow that starts from y (if any), and
draw a new arrow from y to the same value that’s connected to x. You
should now have one arrow from x and one arrow from y, both leading to
the same value on the right.
If you keep this diagram in mind, you’ll understand why the following
happens in ruby:
x = [2,3]
y = x
x[1] = 4
p y[1] # ==> 4
and you’ll also understand why
x = 0
x++
can’t make any sense.
This arrow diagram isn’t the whole picture of course: eval breaks down
the wall between variable name and value, and there are different
bindings in different scopes. But there’s nothing fundamentally wrong
with this picture.