[RAD stands for
Ruby Ape Diaries, of which
this is part V.]
If you look at Ruby code, you keep seeing this little two-character motif
<<, and maybe everyone else already knew about this, but
it sure feels like magic to this farm boy from the Prairies.
Bonus: Lisp speculation.
<< is the name of a method, and you can define it to
mean anything you want, but normally it means “append-to-self”. For a File it
means “Write this on the end”, for an array or list or whatever (and Ruby
doesn’t seem to think there needs to be a difference) it means “add this as a
new element”, and for a string it means “concatenate in place”.
This last operation is particularly useful because, to use Java
terminology, it makes every
String into a
For example, suppose you’re writing a protocol using
and you want to get a trace of the dialog. You say:
<< on “whatever” to
store the trace. So if “whatever” were a file, you’d get a
logfile. But the simplest way to use this is to say:
trace = "" session.set_debug_output trace
Then you get your session built up in the string “trace”.
For the Ape’s trace function, I needed to keep track of who said what, so I did something along the lines of:
trace =  session.set_debug_output trace
Which gave me the dialog in a nice handy list. In practice, I wrapped the
array in a little class and redefined
<< so that I could
timestamp the entries and discard some of the housekeeping like “Connecting
The Moral of the Story ·
Of course, every Rubyist knows this by heart, but it bears repeating: If
you’re writing any kind of logging or data-collection framework, do your
<<. And if you’re building any kind of a data
structure that can grow, don’t forget to implement
Another Example ·
I got a bug report from Hugo Duncan
complaining that the Ape wasn’t doing a good job with relative URIs in general
xml:base in particular. He was right, the Ape was wrong.
The Ruby libraries have a URI fixer
but don’t seem to grok xml:base, so I had to write an
function to take a URI,
the node in the XML tree where it was found, and walk down the tree to the
node building up the appropriate base URI.
First I needed to compute the path from the root to the node:
def path_to node if node.class == REXML::Element path_to(node.parent) << node else [ ] end end
(It’s a pity I’m not preserving Emacs’ nice syntax coloring, but that would
be real work.) This is a straightforward recursive tree-climb that uses
<< to build up the path.
There’s one more little bit of Ruby magic here; the way REXML builds trees,
you’d normally find that the root element has a parent, an instance of
REXML::Document. But maybe not; you can get a situation where
that’s not there and the topmost element’s parent is
hey, in Ruby everything’s an object, and so is
NilClass, so everything just works.
I’ve noticed that this idiom of referring to
irritates real Rubyists. In this case, they’d be right. Because assuming I
eventually switch back to JRuby, those nodes won’t be instances of
REXML::Element any more, but they will still have element-ish
children or whatever.
Lisp · You notice that phrase “... to build up the path”? In a perverse mood, I might have written “... to cons up the path” because, as I would have been informed by numerous emailers if I didn’t pre-empt it here, every MIT undergrad was doing this kind of thing in Lisp by 1970, isn’t it quaint that the world is catching up, etc etc.
And they’d have a point; but Python and Ruby seem to have oozed further into the mainstream than Lisp ever has.
“Why?” is an interesting question, and I think the biggest single piece of the answer is inheritance from Perl’s culture of ruthless practicality. In other words, not afraid to use syntax to make the point; things are generally lists, except when they’re not; attention to typographic values; building hashes and regexes into the language; not requiring you to ever say “lambda”. Any more?
If Lisp’s audience had been harried sysadmins rather than AI researchers, it’d rule the world by now.