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