[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 StringWriter.

For example, suppose you’re writing a protocol using Net::HTTP and you want to get a trace of the dialog. You say:

session.set_debug_output whatever

Then Net::HTTP uses << 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 to...”.

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 output with <<. 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 and 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 absolutize 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
      [ ]

(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 nil. But hey, in Ruby everything’s an object, and so is nil, and nil.class is NilClass, so everything just works.

I’ve noticed that this idiom of referring to whatever.class 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 methods like attributes or 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.

author · Dad · software · colophon · rights
picture of the day
August 22, 2006
· Technology (87 fragments)
· · Dynamic Languages (45 more)
· · Java (123 more)
· · Ruby (93 more)

By .

The opinions expressed here
are my own, and no other party
necessarily agrees with them.

A full disclosure of my
professional interests is
on the author page.