Jach's personal blog

(Largely containing a mind-dump to myselves: past, present, and future)
Current favorite quote: "Supposedly smart people are weirdly ignorant of Bayes' Rule." William B Vogt, 2010

What's the value for a programmer to learn Common Lisp these days?

The value depends on what you already know and whether you want to substitute potentially inferior versions of the thing to acquire or make use of the knowledge. I'll list some ideas of useful concepts you may or may not have picked up already.

First, a lot of languages have closures these days, do you know them and more generally how to tastefully use higher-order functions? When Java 8 came out, I could see a difference between programmers who had useful experience or instruction (Scheme + SICP is still great on this) using closures elsewhere prior, excited programmers who were using them for the first time even if frequently not tastefully, and old programmers who had never strayed outside their lane and look at any new language feature or evolution that they now have to learn and contend with to keep up with a shady eye, never mind the potential benefits.

Second, some languages have something like macros, how familiar are you with metaprogramming? Maybe you'll be satisfied with C++? A comparison from the author of the CLASP implementation who is an expert in both langs: Lisp macros are to C++ templates as poetry is to IRS tax forms.

Third, do you know OOP, or perhaps you know it quite well from things like Java/Python/C++/Ruby/JS and dislike it? The Common Lisp Object System (CLOS) was the first ANSI standardized OOP system and yet it's a lot different from other attempts. In particular, it does not couple classes together with methods, they are defined separately which avoids a lot of common OOP problems while giving you multiple dispatch for free (eliminating some verbose design patterns too). It's also got less commonly seen things like metaclasses (with a whole book written on just the meta-object protocol highly praised by Alan Kay), multiple inheritance, a way to redefine classes and reshape existing objects at runtime (overload an 'update-instance-for-redefined-class method), and a poor man's initial support for maybe 70-80% of the value of aspect oriented programming with :before/:after/:around method combinators out of the box that can be further augmented if needed for the full value. Some of the ideas can be had with effort (perhaps done for you already via libraries) in other langs.

Fourth, do you know about conditions and restarts, a way to handle errors that's not just goto error or classic stack-unwinding exceptions? There's a whole (short) book ("The Common Lisp Condition System: Beyond Exception Handling with Control Flow Mechanisms") on just this topic if individual chapters/essays elsewhere aren't enough for you. I don't know a good alternative for getting this concept, thus the value of it may be limited to whether you can actually use it or an imitation (the book author did implement a version for Java:

Fifth, do you have experience in incrementally writing and debugging a program as it's running, or have you only ever done the usual edit > compile > run > observe and repeat cycle? Common Lisp is still the best for this, Clojure is ok, Java with JRebel gives you maybe 80-90% of the practical benefits. TDD maybe gives 20-30% of the practical benefits while being tedious. Some people definitely do not like the style, but if you haven't seen the style to determine that for yourself, you're missing out. (And if you're freaking out about error checking, you can get some compile-time warnings from SBCL about bad types or missing functions and so forth; they're just warnings instead of errors because you can fix them as you go, you can redefine (even if you're in a debugger context) and continue rather than restart everything and lose any state. In SBCL, redefining a function also recompiles it for you. 'compile and 'compile-file are standardized built-in functions to the language you can invoke at runtime, rather than a separate program.)

As for editors, you don't have to use emacs. (I prefer vim.) gives a list of alternatives besides those two. The main things IMO that you need as far as editor support goes: highlight matching parens (basically everything), and ability to talk to the running Lisp to provide the features of my fifth point. To elaborate even further on that, such support gives you redefinition, debugging (breaking/stepping/tracing), disassembling, intellisense-style function doc and even symbol auto-complete, and jump-to-code/cross-referencing features, all part of Lisp itself and conveniently/portably accessed with regular Lisp code talking to the editor typically over a socket rather than needing to be implemented externally. The main development feature, editor or otherwise, still lacking from anyone (though someone was working on this, I haven't followed up in a long while) is mass auto-refactoring; in practice it's not a huge limitation because you don't couple things as heavily as in other languages that necessitate frequent huge refactorings, and you can use the same sorts of tools people used just fine prior to semantic mass-refactoring tools becoming more common. (I use Grepper with vim for mass-rename.) Fowler's 2nd edition of "Refactoring" uses JavaScript with no fancy tools in part just to show the point that the discipline isn't tool dependent anyway.

[This was an answer I gave to a HN comment that got a bunch of upvotes, seems worth reposting here.]

Posted on 2023-06-28 by Jach

Tags: lisp, programming


Trackback URL:

Back to the top

Back to the first comment

Comment using the form below

(Only if you want to be notified of further responses, never displayed.)

Your Comment:

LaTeX allowed in comments, use $$\$\$...\$\$$$ to wrap inline and $$[math]...[/math]$$ to wrap blocks.