Austin Ziegler wrote:
...
No, it's best to forget the concept of a Ruby variable as a shoebox. It
doesn't *hold* anything.
In C/C++, a variable is a shoebox. This shoebox has a physical location
and dimension (the address in memory). One shoebox can hold the location
of another shoebox. That's a pointer or a reference (under the covers,
they are the same in C++).
A variable in Ruby is a sticky note (like a Post-It). You can put that
sticky note on an object, or you can put multiple sticky notes on an
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.
···
--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407