Sorry for the long post. I’ve been observing several threads recently
where the concept of assignment, mutablility and operators are
discussed. Folk wonder why “++” is not an operator and wonder why you
can’t assign to self. They confuse the difference between modifying a
variable and modifying an object.
Now some of this is just being new to the language and you quickly
overcome it. I also think a good deal of the problem is that many
programmers new to Ruby come from what I call “shoebox” languages, and
changing the way you think about variables and assignments in Ruby will
help you climb the learning curve a little faster.
So, here’s some thoughts on variables and assignment. If this helps you
great. If it doesn’t, well, that’s ok too.
SHOEBOXES AND BINDINGS
···
When I was first learning about programming (mumble mumble) years ago,
variables were explained to me as shoeboxes. A variable name denoted a
location in memory (a shoebox) which can hold things. You put values
into the shoebox and they stay in there until you put something else in
there. Each shoebox is exactly the right size to hold the type of data
you put into it. Integers fit in int-sized shoeboxes and floating point
numbers fit in float-sized shoeboxes. Pointers can be added to this
model by envisioning labels (addresses) for each shoebox and storing a
shoebox label in another shoebox.[1]
Assignment is the act of copying a new value into one of your shoeboxes.
This model works really well for understanding FORTRAN (the language I
was learning at the time) and Algol, and reasonable well for C and C++.
HOWEVER, this is exactly the wrong way to think about Ruby variables.
Consider the code …
a = b = "Hello"
The shoebox model encourages us to think that the string is in the 'a’
shoebox and another string is in the ‘b’ shoebox. Therefore we are
surprised when modifying a changes b. To explain this within the
shoebox model, we resort to talking about references and how the
shoeboxes ‘a’ and ‘b’ don’t actually hold the string object, but hold a
reference to it.
All of this is perfectly correct, but I believe there is a better model
to use for Ruby variables.
In Ruby, the variable ‘a’ does not represent a shoebox that can store
things. Instead, it represents an association between a name and an
object. We call this association a “binding”. Executing the code …
a = "Hello"
binds the name ‘a’ to the string object “Hello”. References to 'a’
after the assignment will lookup the name ‘a’ in a dictionary of
bindings and will find the object currently associated with ‘a’. We no
longer need think of variables as shoeboxes containing objects, but as
names associated (bound) to objects.[2]
I see a number of advantages to this point of view.
(1) The distinction between immediate values (like Fixnum) and reference
values (most everything else) becomes invisible.
(2) Multiple assignment statements (like ‘a = b = “Hello”’) is explained
in terms of binding the names ‘a’ and ‘b’ to the same object. No need
to talk about pointers or references.
(3) Assignment becomes an operation that is outside an object. Objects
don’t care what names they are bound to. Therefore binding is not an
operation on an object and won’t ever be a method on an object. This
helps explain why “+=” is not a method and why “++” can’t be implemented
as a method.
I found that adopting this view has helped me understand Ruby better. I
hope it helps you as well. Comments and feedback are encouraged.
Footnotes:
[1] I used this technique to explain pointers when I taught a class
in C, except I used styrofoam cups with labels instead of shoeboxes.
I would write on yellow postit notes and drop them into the cups
(variables). Each cup had a label, so to represent a pointer I
would write another cup’s label on a postit and put it in a cup
representing a pointer variable. It was actually a rather effective
in demonstration.
[2] Variables as name bindings is not unique to Ruby. I first
encountered the concept when learning Lisp (what I learned after
studying FORTRAN). I’ve also read threads in the Python newgroup
where someone was offering a similar explaination of variable
binding for Python. I’m sure there are many other languages where
binding is a better model than shoeboxes.
–
– Jim Weirich jweirich@one.net http://w3.one.net/~jweirich
“Beware of bugs in the above code; I have only proved it correct,
not tried it.” – Donald Knuth (in a memo to Peter van Emde Boas)