On: Lisp, On Lisp, and Myself

Started
Published
Last updated

Happy new year!

It’s actually been a few months since I read On Lisp,[1] but I’ve been thinking a lot about Common Lisp, henceforth referred to as Lisp, lately.

No

It’s easy to get turned off by Lisp. The early versions of the standard are easily double my age,[2] and it shows in many places. car and cdr are great names,[3] but terpri and multiple-value-bind are not. Those last two are bad for opposite reasons, terpri is an obscure abbreviation and multiple-value­-bind is verbose.

That’s an inconsequential example, but I could go on about these annoyances for dozens[4] of minutes—I haven’t even mentioned other frustrations, like

That last nit is particularly exasperating because Doug Hoyte insists on venerating it as a feature in his otherwise compelling and elucidating Let Over Lambda.[7]

Minor issues like these kept me from sticking with Lisp for any substantial amount of time, and made Schemes look all the more appealing.[8] Shoot, I even made the barest of contributions to Racket, the most pragmatic Scheme dialect.[9]

But, you know what? All of this doesn’t matter. It matters a little bit, but it doesn’t matter!

Yes

To be honest, I skimmed the full programs in On Lisp; what grabbed me were the utilities. Here’s the magical thing: Lisp lets you solve any[10] problem with the language. Often, easily! Lisp isn’t the perfect programming language: it is the best substrate for your perfect programming language.[11] That’s why I recommend On Lisp: it demonstrates what makes Lisp not just good but great. Give it a shot; it’s free.

Example

If I had to pick a single example that best convinced me that Lisp was for me,[12] it would be this:

Take this Scheme code:

(define ( f g)
  (lambda (x)
    (f (g x))))

and compare it to this Lisp code:

(defun  (f g)
  (lambda (x)
    (funcall f (funcall g x))))

No contest, right? Even if you don’t care much, this is the kind of stuff that gets to me!

But what if I just…

(defmacro fpromote ((&rest fs) &body body)
  `(flet ,(loop for f in fs
                for args = (gensym "args")
                collecting `(,f (&rest ,args) (apply ,f ,args)))
    ,@body))

and then…

(defun  (f g)
  (fpromote (f g)
    (lambda (x)
      (f (g x)))))

See? For the longest time, the separate function and value namespaces in Lisp turned me off, and with five lines of code, I eliminated the problem in many cases that I encounter—I use fpromote almost twenty times in my utils.lisp!

Myself

There’s an essay that has been submitted almost two dozen times to Hacker News titled The Bipolar Lisp Programmer.[13] I don’t think I’m the titular bipolar programmer, but the essay comes to mind often when I’m doing Lisp stuff. The most recent instance of a minor mania? Writing the example section. I am grateful that I don’t suffer from any serious depressive episodes, but momentum is as important for me as it is for everyone.

Advice

Here’s five[14] pieces of unsolicited advice for you and me:

  1. I’m not sure there’s any value in trying to convince people how great your favorite programming language is. xkcd 386 is my desktop wallpaper for a reason.

    I was originally intending to have no Lisp code, there’s plenty of Lisp evangelism out on the web, but I couldn’t resist making one attempt.

  2. Experimenting with programming languages is so fun. Do it as much as you want to! However, use the programming language you like the most all the time. In the hands of someone experienced with solving their own problems, even a language like C++ can become an exceptionally useful tool that is a joy to use.
  3. Publishing should be your default. In my experience, it is fascinating to look back at my old code, and it is incredibly fun to discuss your code with others—if fun isn’t enough to motivate you,[15] remember that you’ll realize many things you could have done better… as soon as other people can see your code :P. Also, most software forges let you “publish” things privately, so you can hedge your bets. I’m always bummed when I don’t have access to my old code.
  4. Linked lists suck, but use whatever is most convenient for your first draft. The adage goes that “nothing is more permanent than a temporary solution,” but, especially for code you write for you, consider this alternative adage: “if it’s stupid and it works, it’s not stupid.”

    “[A]bout 97% of the time: premature optimization is the root of all evil.”

    ― Donald Knuth

  5. Finally, learn from your mistakes, but wallow not: push forward and do what makes you proud.[16]

  1. Physically; it was at my university’s library! This is what we in the business call an “epic win!” ↩︎
  2. Not that I’m old at the moment :P. ↩︎
  3. Fight me. ↩︎
  4. Dozens! ↩︎
  5. I actually read PCL a year or so before On Lisp. ↩︎
  6. It’s a good chapter, don’t get me wrong. ↩︎
  7. Alas, I’ve only read the free chapters at time of writing. All in due time! ↩︎
  8. The Revised Revised Revised Revised Revised Revised Report on the Algorithmic Language Scheme, particularly as implemented by Chez Scheme is the most appealing to me. Please don’t fight me on this; I just don’t have the energy for it. ↩︎
  9. Racket is more accurately described an infinite set of interoperable Racket dialects. It’s complicated, and interesting, but racket/base is my go-to.

    By the way, I’m still (somewhat) active in the official Racket discord guild. It’s a great group! ↩︎

  10. Sometimes, suboptimal performance is insurmountable even with (optimize (speed 3) (safety 0)) and define-compiler-macro (another inconsistent name!), but SBCL is a dang hard compiler to beat in the dynamic space. ↩︎
  11. Racket probably wins if you want it to be for more than just you. It’s amazing! ↩︎
  12. I do. I have twenty minutes left to finish this post :P. Edit: Went well over. Oh well. ↩︎
  13. Fifteen years ago, it was described as “an oldie but a goodie,” which is funny. ↩︎
  14. This grew from two to three to four to five. Embarrassing! ↩︎
  15. Laaaaaaaame!!!!!!!! ↩︎
  16. It’s easy for me to agonize over past wasted time, which wastes more time. The second best time is always now! ↩︎