On Jan 6, 2006, at 7:21, Jim Weirich wrote:

> Dave Howell wrote:
>> A variable is a box.
>
> Hmmm ... see http://onestepback.org/index.cgi/Tech/Ruby/Shoeboxes.rdoc
> for an alternate view.  I think the mental model of "boxes" as 
> variables
> doesn't work so well for Ruby.

Oh, I definitely agree. But again, my explanation is specifically for 
Ruby newbies and beginners, especially those to whom "symbols" are new 
territory. But I think explaining variables containing bound references 
kind of has to follow the concept of variables as containers.

Gavin used fishing line to build a referencing metaphor. I've usually 
used colored yarn, arrows, or maybe laser pointers on little tripods 
when I'm trying to work it out in my head. :)

Reading Gavin's post and Jim's blog article dropped a new metaphor into 
my head, one that, the more I test it out, the more I like it.




Assume that all your Objects are stored by Ruby in something resembling 
an old post office mailbox room. Hundreds and hundreds of mailboxes, 
all numbered, each with a key in the lock, waiting to be used. Ruby 
stores strings and numbers and other Objects in these mailboxes. An 
Object cannot exist unless it's in a box. Now, I *think* that Ruby 
might let you access these containers by number. I know C will. But why 
would you want to do that? Extremely confusing and inflexible.

	myName = "Dave"
	
And with that, Ruby builds a String, puts it in some mailbox, and hands 
me a key with a tag that says "myName" on it. (The keychain tag, by the 
way, is a classy metal tag with the writing engraved on it, not one of 
those cheap plastic doodads with the paper you can slip out and write 
on.)
	
	currentUser = myName

Ruby makes a key tag with "currentUser" on it, duplicates the myName 
key, and puts it on the "currentUser" keychain.

	coolName = String.new(myName)

Ruby makes a new String just like the old one, puts it in a different 
box, and puts the new different key on a chain with the tag "coolName."

	currentUser.replace("Sam")

Since "replace" replaces the contents of the String Object, Ruby takes 
the key on currentUser, opens the box, takes out the String inside, 
changes its contents to  "Sam", and puts it back. Obviously, if I now

	print myName

I'm going to get "Sam" because that's what's in that box now: a String 
containing the characters "Sam".

	population = 486

I have a key with a tag that says "population" that opens a box 
containing a FixNum(I think?) that contains the number 483.

	parkingSpaces = Array.new(40)

I have a keychain labeled "parkingSpaces." In the corresponding box is 
a board with a bunch of nails numbered 0 through 39. The nails are 
empty.

	parkingSpaces[3] = "VP Operations"

Now nail #3 has a key on it to a box that contains a String that 
contains "VP Operations."

The difference between an Array and a Hash is, with an Array, the nails 
are numbered, but you just hang plain keys on them, keys with no tags 
attached. With a Hash, you have a bunch of nails (or maybe it's just a 
bin) that are NOT numbered, but the keys all have tags.

Ruby knows which key opens which box because the keys have their box 
number stamped on them.

	myName.object_id

But why would I care (most of the time) what box number my information 
is in, when Ruby is so willing to go get my mail and bring it back for 
me? :)

	TheAnswer = 42

Constants are like the kind of key chains you see for the bathroom at a 
gas station or something. The keychain is extra big (that big Capital 
Letter in the front that won't fit in your pocket), and once you put 
the key on, you can't change it. You still get to decide what's written 
on the tag, and you can put all sorts of things in the mailbox.



[As I started to write this next section, I realized that how this all 
works is still very unclear to me. Let's see if I've figured it out . . 
.]

	sillyNum = population + 14 / "5".to_i

Ruby make a new keychain tagged "sillyNum." There isn't a key on this 
yet. That's what "nil" is; a keychain without a key.

Ruby takes my "population" keychain and opens that mailbox. She reaches 
in to activate the enclosed FixNum's _plus_ method, which extends a 
little chute labeled "put number here."

The next thing on that line, the number 14, is a Literal. The Pickaxe 
book isn't really telling me exactly what happens here, but by playing 
around in irb, the metaphor that seems to let me correctly predict 
behavior is that Ruby manufactures a brand-new FixNum on the spot with 
a 14 inside. Objects can't exist outside boxes, but I have no idea if 
she extracts the value 14 from her new FixNum or if she whispers her 
new FixNum's box number into the ear of the FixNum inside the first 
box, but somehow the _plus_ gets whatever it wanted. It spits out a new 
FixNum object that contains the value 500.

I think that Ruby puts this in a box and puts the key for this box on 
the sillyNum keychain.

Now she activates the _divide_ method on the new Fixnum, and another 
"put number here" chute opens.

Finally, she constructs a String object that contains the character 
"5", and turns on the to_i method on the String, which pops out a 
FixNum object containing the value 5? The FixNum 5 gets dropped into 
the "put number here" chute, and the value of the sillyNum FixNum 
becomes 100? Or maybe it also makes a new FixNum with a value of 500. 
The keychain for the box containing the "5" String is thrown away. If 
another new FixNum was created, then Ruby also takes the key for the 
_500_ FixNum off the sillyNum keychain and throws the key away. She 
puts the key for the _100_ FixNum on the keychain instead. I'm not sure 
which, but the end result is effectively the same.

Of course, if she keeps putting things in boxes then throwing away the 
keys, pretty soon there are a lot of Objects in boxes taking up space. 
Ruby can always make new keys, but if there's no keychain with that key 
available, then the mailbox's contents are inaccessible to the 
programmer. When Ruby has a bit of spare time, or when too many of her 
mailboxes have old Objects but no keys, she goes through and empties 
out all the obsolete Objects, so she can reuse the mailboxes later. 
This is called "garbage collection."


A Symbol is kind of like a Constant, except the only thing that the 
mailbox can contain is a Symbol. A Symbol is kind of like a String 
encased in acrylic. Also, Ruby engraves the key tag with exactly what's 
inside the plastic. As a bonus, Symbols gets a "secret numeric 
identity" engraved on the bottom.  (It's not the mailbox number.)

Symbols have almost none of the fancy accessories that come with 
Strings. About all you can do with them is get a String containing the 
name/contents of the Symbol, or get an Integer that contains the 
Symbol's "secret numeric identity."

They differ from Strings in another way.

	print "Dave".object_id
	print "Dave".object_id
	print "Dave".object_id

results in something more or less like

	3945266
	6941506
	2937746

but

	print :Dave.object_id
	print :Dave.object_id
	print :Dave.object_id

looks more like

	8873230
	8873230
	8873230

That's because, unlike literals, Ruby doesn't throw away Symbol keys. 
Every "Dave" results in a new String in a new box, and unless you 
assign it to a variable (aka have Ruby put it on a keychain with a 
tag), she throws the key away. But with a Symbol, Ruby *always* makes 
the tag for the keychain when she makes the Symbol.




OK, that's enough of that. No metaphor is perfect, but duplicating keys 
seems to work quite well across a remarkable amount of territory. So 
what did I get functionally wrong (it doesn't really work quite like 
that), and more importantly, what did I get effectively wrong (it 
doesn't even *appear* to work like that). :)