(win-p :Common-Lisp) --> T
July 28, 2008
This weekend, following a stimulating discussion on Friday with Jose, I decided to walk a little further down the road of Lisp, and more specifically Common Lisp. After a couple of days with Peter Seibel’s Practical Common Lisp, I am surprised to report that I can reasonably mutter out a Lisp program, albeit a little slowly, and also that I enjoy it very much.
I’ve tried to get into Lisp several times in the past. The first time my brain was still all soft from C, and the prefix notation scared me off. Hey, I was still in Visual Basic rehab at the time, trying to make the nightmares stop.
The second time, through an AI course, I got decently fluent in very basic Emacs Lisp. Not actually interacting with Emacs that much, just using elisp as a Lisp dialect for getting the course projects done (for various reasons, elisp is a bit of a stupid choice of dialect for general-purpose programming, but never mind). Being young and stupid, I thought that I could just switch gears and pick up Common Lisp in my stride.
I tore through some random Common Lisp tutorial with ease, reached macros, and my head exploded. It wasn’t its fault, it had never seen anything like that. I had a gut feeling that macros were exceedingly cool, kind of the light sabers of programming: an elegant weapon for a more civilized age, that can cut through just about anything while making a cool sound. But I wasn’t ready. So retreated once more, back to the familiar pastures of C, Python and Java.
Last year, after rebuilding and consolidating my brain in various ways, I tried again. This time, I understood how macros worked, and was suitably impressed at being able to run code at compile time to produces more code. But I lost interest. It seemed to me that Common Lisp was being used for really byzantine pieces of software, which could only be described with multiple uses of the ‘meta-’ prefix, and just generally spent a lot of time not doing anything of practical value. Doing anything that might benefit mere mortals seemed just out of grasp.
And so, I went back to the pastures of C, C++, Python, and other old friends. To my surprise, I did sometimes find myself pining for macros once or twice, when building particularly horrid little pieces of code that were trying really hard to abstract away concepts with no help from the language.
Which brings us to here and now. I’ve spent two days with Seibel’s book, which addresses precisely what I felt last time, that Common Lisp cannot be used for pragmatic development of everyday software. The book elegantly demolishes this illusion by digging into a cornucopia of practical programming projects in Common Lisp, including:
- A unit testing framework, using macros to define new syntactic constructs that can concisely define new tests, and abstract away the ugly book-keeping machinery
- An ID3v2 tag parser. The approach used here is to first create, using macros, a domain-specific language for describing the structure of binary formats. The code to read, write and manipulate the tags is then derived from this very beautiful and concise definition.
- A Shoutcast streaming server, demonstrating everything from network I/O to keeping an MP3 database to using our ID3v2 tag library
- A little HTML template language. This little language lets programmers describe the HTML object tree in a delightfully minimal manner, as well as mixin some basic rendering logic (conditional blocks, looping …). Peter then goes on to write both an interpreter and a compiler for this language, showing an abstraction technique that is still something pretty exclusive to Lisp: the creation of new languages to concisely express solutions to problems.
The great thing about Lisp, as so many have said before me, is the REPL. If you’ve ever used Python, Perl or Ruby, you know what I’m talking about: the ability to establish a dialog with the language. You feed it something, it tells you what it thinks. You change the code slightly, build up a little more functionality, tell the language about a new abstraction you’d like it to understand… And all the time, you have at your fingertips the ability to ask Lisp “What do you think? Does this look good? Could you evaluate this for me real quick, to see if I got it right?” I don’t think that anyone coming from a purely edit-compile-run language background can really grasp the basic joy that there is in having a conversation with your language to build software. It’s a very pleasant way of programming, and on a fundamental level it defies description. You have to try it.
Given how much Lisp code I’ve written, I am but a humble grasshopper. I’ve barely started my journey down this path, and to paraphrase Feynman, if I think I understand Common Lisp, I probably don’t understand Common Lisp. Not yet at least. But, while writing the 70 lines of Lisp code that make up my first non-trivial program (a parser for the wire format of Google Protocol Buffers, if you care), there were brief moments when the clouds parted, and I caught a glimpse of where the path leads, all the way to the horizon.
I think I may enjoy walking the path.
The Road goes ever on and on
Down from the door where it began.
Now far ahead the Road has gone,
And I must follow, if I can,
Pursuing it with eager feet,
Until it joins some larger way
Where many paths and errands meet.
And whither then? I cannot say.