From: Joel VanderWerf Date: 2007-09-30T08:16:49+09:00 Subject: Re: a = Dog.new # a is not a pointer and not a reference? 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