On Lisp Enlightenment

Common Lisp is hard to learn and won't turn you into an elite hacker. If you are interested in my journey, read on. In college, my research advisor used Emacs. Naturally, I was indoctrinated into the church. Eventually, I would discover the delightful text manipulation language that is Vim. By that point I had been such a heavy user of Emacs, evil was the only way I could reasonably run Vim.

Emacs, for the uninitiated,1 is configured in a dialect of Lisp called Emacs Lisp. After a few years of copy-pasting spells into my .emacs, I wanted to be able to develop my own magic. The development of any skill begins with research, and ends with practice. I learned about Common Lisp, and Scheme, and "The Structure and Interpretation of Computer Programs" (SICP). I read "The Little Schemer".

I desperately wanted the Lisp enlightenment. A moment when the parentheses would fall away and programming would become as effortless as thinking. The code and data would merge together and domain-specific languages would just appear to me and solve the problem in front of me.

Here's the thing though, it never came. I tried so hard. At some point in my lisp travels I discovered StumpWM. A tiling window manager written in Common Lisp. Surely, if used this every day I would have to learn lisp, and the enlightenment would follow.

I did have some important insights into programming. The exercises in SICP truly changed the way I approached coding. Learning about layers of abstraction and functions as first-class citizens were revelatory. I eventually started maintaining StumpWM as an open-source project. It got a new lease on life, and I got an extremely rewarding hobby. I didn't (and still don't) write very much lisp for StumpWM2. I did learn an awful lot about X11 though.

I think the lisp enlightenment is oversold. Common Lisp is a nice language, and knowing it (and other dialects) has allowed me to notice and appreciate its influences in other languages (notably Mathematica and JavaScript3). It has some really uncomfortable gotchas that new users immediately cut their fingers on.

The first is which lisp? Scheme, Common Lisp, and Emacs Lisp are just a few branches of a very confusing tree. Suppose you settle on Common Lisp, now you have to decide on which implementation. Do you choose Clozure Common Lisp? Steel Bank Common Lisp? CMUCL, GCL, ACL?

Let's assume the intrepid lisp hacker (ILH) installs SBCL, when you invoke it on the command line you are greeted with:


This is SBCL 2.1.11.debian, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses.  See the CREDITS and COPYING files in the
distribution for more information.
*

This interface is next to useless, there's no readline support, no ability to move through the history, and no easy way to edit lisp forms. Our ILH needs to embed their lisp implementation in an environment (Emacs is the only real game in town, sorry vim users!).

Let's assume our ILH is undeterred and manages to get a viable environment set up. Maybe they even discover Quicklisp and a decent language tutorial. They start writing a non-trivial program and are beginning to get confident with all the parentheses. Inevitably they will write something like this:

(if (= i 10)
    (print "i is 10!")
    (* i 2)
    (+ i 3))

Assuming that i is 10, users of other languages may assume that it will print "i is 10!" and i will have the value 23 when this is all done. In fact, this will signal an error because if only takes three expressions, the condition, and two expressions for true or false cases.

Our ILH will discover that when no 'else' is needed they should use when and unless. Someday they'll need an honest if clause, but they'll need multiple sub-expressions and they'll discover progn:

(if (= i 10)
    (progn (print "i is 10!")
	   (* i 2))
    (+ i 3))

But progn isn't "Lispy", to be idiomatic they should use cond.

Our ILH continues their journey, and since Lisp goes way back, they have to learn the difference between car and cdr. In the same breath that they learn this, they also learn that the modern equivalents first and rest are preferred. Culturally, everyone still uses car and cdr.

This is just a small slice of the friction that comes up when getting started with developing in Common Lisp. I'm not even touching asdf, package management, and compilation. Developing in Lisp comes with significant upfront costs to get started.

If you're getting started in Common Lisp, be patient. At some point, all of the quirks and idiosyncrasies will feel normal4. If you have started exploring Lisp to level up your programming skills, read SICP and do the exercises. If you are interested in Lisp for its homoiconicity, or language design, learn racket and implement 'make a lisp' in your favorite language. If you want a weird, crufty, window managing experience, come try StumpWM!

Footnotes:

1

If you're reading this… you are probably initiated.

2

This is a topic for another post. It has been one of the most rewarding, and frustrating, experiences that I've had.

3

Incidentally, SICP was re-released recently with JavaScript as its main language. I think it this was the right move, and have found JavaScript delightful to develop.

4

I got burned hard by the if example and it was hard to write today without it feeling very wrong.