Comment by klibertp
1 day ago
I tried using CL this year for a new version of my personal static site (blog) generator.
Yes, it's incredible and still an alien technology in some respects. Native AOT compilation at the level of functions with hot swapping - and without any ceremony, always available in the IDE - is one of them. As the OP writes at the end, only Smalltalk and Erlang come close.
But, when viewed objectively, in 2025 CL is quite behind in some aspects:
- Only one commercial IDE offers a true graphical debugger. Both SLIME and SLY (I'm not sure about stickers) fall behind JS or Python environments.
- Asynchronicity is based on explicit callbacks or callbacks wrapped in promises (and some macros). No async/await, no coroutines. Since writing async code is harder, people default to sequential code and a thread pool. For IO-bound apps, this unnecessarily adds synchronization problems that would be mostly avoided in single-threaded concurrency.
- Tiny ecosystem of libraries. Due to the stability (or stagnation) of the language, a lot of old code still works, but even with this, finding what you need on Quicklisp can be challenging.
- The stdlib is old, crufty, and quirky. It's also very small by today's "batteries included" standards. Initiatives like CL21 or CIEL try to alleviate this somewhat.
- Even in SBCL, the type system is limited compared to MyPy, TypeScript, or TypedRacket.
- Bolting packages (module system) on top of symbols leads to some problems in practice.
- The progress in CL development is severely hampered by the set-in-stone standard, small pool of users, and the need to reconcile 10 different implementations.
It's still a nice tool for many uses, and the interactive development is indeed comfortable and productive. Still, if nothing significant happens, I don't think CL will have a chance to gain popularity again. Up until now, a successor language was hard to justify - despite some shortcomings, CL was still a language from the future. Now that future is largely here already, so the shortcomings become more and more glaring. There's SICL, but it'll take another decade (if at all) before we can expect results from that.
I'm now looking at Jank and Gerbil with some expectations, though I think I'll stick with CL in my current project.
> fall behind JS or Python environments.
I dunno what you are using but we are a small team working on large codebases; one in js/ts mix, one in python and one in cl. Everyone cannot wait for it to be CL time; everything js and especially ts feels so incredibly clunky and half baked. The debuggers are awful and actually don't even stop on breakpoints a lot of the time for no apparent reason.
For most things in cl you have libraries (async etc) and for the rest you roll your own (much) faster than you can try out the tearinducing garbage on npm to figure out what half baked buggy thing might fit your purpose (before it gets hijacked by some north Korean hacker group of ofcourse). With LLMs this has become way easier.
Using the strong typesystem cl has and then adding on coalton when you need it, I prefer over typescript, if only for the speed of dev / no noticeable recompile.
> Bolting packages (module system) on top of symbols leads to some problems in practice.
Packages are namespaces, unrelated to modules. They are not used to organize dependencies but to remove ambiguity of naming and to provide encapsulation.
> The progress in CL development is severely hampered by the set-in-stone standard, small pool of users
The language is extensible, compilers do get new features added, sometimes in a coordinated manner. Standard being stable is not that significant an obstacle to moving forward; pool of users being small is much more noticeable. Yet more noticeable is that community is less healthy than the Emacs one. This comparison is valid because development in Emacs Lisp is attractive for the same reasons, unique to it and CL; they also happen to have extremely similar syntax. Elisp is moving forward steadily, and in recent years quite rapidly. CL would progress forward similarly, or better, had it had something like Emacs that provided that synergetic effect.
It's funny but I think your exact comment could have been written 10 years ago, substituting 2025 with 2015. Some things might be ±2 years. This observation could be seen as both a positive and a negative about both the language and people writing about it.
Things have changed since 2015, though, and in 2015 looking back at 2005 things had changed too. (Quicklisp was only on the scene in 2010, which is somewhat late compared to its equivalents in other languages.) Popularity-wise, I continue to be positive about CL's global future, even if nothing is done about your bullet points. Over the years I keep noticing new software, new implementation features, the occasional new book, new papers, new jobs, and new people writing stuff, I expect that to continue. Some long-standing companies and systems are still going, avoiding the death of a total rewrite or just better competition, some of them like managing train schedules are older than me. It looks like a living and (slowly) growing ecosystem. It won't ever again enjoy a top-10 language status by making technical changes, but I don't think many people care. (There's a similar level of not caring when it comes to non-GC languages and how their overall job market share is probably not going to shift from ~10% any time soon (barring the potential of forced mass early retirement due to AI).)
I was considering a more argumentative reply to your bullet points because I think they're not quite correct... There's a lot of nitpicking that could be done, and further elaborating the nuances might lead to a conclusion that, to the extent the points are true, they don't really matter -- in other words, my reaction to the list even in its strongest form (by my views anyway) is still kind of just a big shrug, so why bother trying to argue with it? I'll keep using Common Lisp. (Even despite my own pet complaints not on your list.) And given your final statement about sticking with it, I wonder if you also kind of shrug at the importance of those things.
> I wonder if you also kind of shrug at the importance of those things.
Yes, to an extent. I suspect I could nitpick on the points ("but X still works", "this isn't how you work with CL", "it's still better than alternatives", "you can work around that") just as easily as you. I still like working with Common Lisp, after all. Even the worst offender on my list - no native coroutines (or continuations) support - was true for both Python and JavaScript for most of their history. And in their cases, there was no way to sweeten the syntax with macros (as BlackBird does for CL). So yeah, these are all shruggable, even if ever more embarrassing as time passes and the rest of the world leaves some of the issues behind.
for folks looking for libraries: https://github.com/CodyReichert/awesome-cl/
(I don't know for popularity but my personal opinion is that CL is still unmatched: this level of interactive development + good debugging tools + excellent implementation that compiles to fast machine code + fast startup for binaries + self-contained binaries + stable yet improving language, implementations and ecosystem + connect from a running program + commercial vendors if you need + … such a unique and productive set)
(re. the type system: https://github.com/coalton-lang/coalton/ for a Haskell on top of CL now)
If you look at awesome-cl you may surmise that Common Lisp has a bit of a dearth of libraries, but a glance at OCICL's repositories shows 79 pages worth of libraries, and Ultralisp even claims to have 2,170 projects. So while it's not at the level of C, Java, or Perl; it's nothing to be sneezed at either.
The fact is that it's so easy to write your own code in CL, that the majority of glue code in NPM, Maven and the likes don't make sense to be written.
An example can be taken from a comparison between VS Code and Emacs. In the former, you have a whole browser engine and quite a bit of code to implement an editor on top of that. In the latter, you just have some primitive and the rest of it is LISP implementing multiple applications. LISP encourages less layers because the data structures and the language are so flexible.
I'm curious what you mean by a graphical debugger? What can you not do debugging lisp that you can for js/python?
My bad, I mean source-level debugger. Something that allows you to step through forms as they are in the source, unexpanded and not decompiled. It should allow jumping to a line or over an expression, continuing to a point, seamlessly stepping into subroutines, and stepping out of expressions. It would be nice to have single-activation and conditional breakpoints. Variables in the executed portion of the code should be annotated with their values. Sometimes watchers - forms auto-evalled in each frame - are helpful, though these are implemented in some CLs, IIRC. SLY's stickers are close, but they are gathered during execution and replayed later, so the break-edit-recompile-redo workflow doesn't work with them. My experience debugging CL using SBCL and SLIME reminds me of debugging CoffeeScript in a browser before source maps were a thing... It's still 100% doable, just less convenient.
Cool, I'm assuming this is largely driven by mouse usage, as well?
I'm always baffled by how long it has been since I was used to step debugging. It was definitely something that was huge when I was learning, but seemed to get left behind by so many practices.
My general memory is that it was growing and the likes of JRebel were aiming for very powerful uses of debugger connected development experiences. Eclipse, as I recall, have their own compiler specifically to let you debug code that isn't completed. Then, cloud technologies largely came and many just lost track of what could be done.
A fun example, I remember senior engineers at Amazon that didn't know you could hot patch Java while step debugging. Something that they had largely never had a chance to do, because of the standard deployment processes they had been used to.
To the direct point, I am somewhat surprised these aren't doable in Common Lisp. I saw examples showing these years ago, just without the GUI affordances that were in some of the other IDEs. https://malisper.me/debugging-lisp-part-5-miscellaneous/ has examples of the trace command offering conditional breaks and such. Sounds like there is the functionality, but lacking the visual cues/affordances?
2 replies →
CMUCL has a graphical debugger.
Unfortunately it looks like only if you are running X11 which cuts most people out.
That was such an unexpected claim, I had to look up on which platforms CMUCL currently runs. Seems it has been ported to MacOS (which I take you are referring to as there are perfectly fine working X11 servers available for M$ Windows). Kudos. If I'd be using MacOS, I'd have also a look at Clozure CL (CCL).