1INTRODUCTION

INTRODUCTION

Common Lisp is an old programming language that hasn't changed since it was standardized. That means that any learning material produced for the language is still useful even today. You can read Touretzky, Norvig, etc. and learn from people far smarter than me.

However, the methods of teaching material, the culture of the people reading the material, and the problems or projects presented in the material may not be as relevant to modern audiences. Touretzky writes for new programmers and doesn't even teach Lisp's OOP facilities; Norvig teaches first principles of programming geared toward old fashioned AI; SICP is heavy on math and wasn't written in an age of ubiquitous ecosystems like JavaScript or Python; Steele wrote a language reference, not a tutorial; various other authors focus on macros, CLOS, etc. These older teaching materials are still irreplaceable masterpieces (Norvig perhaps the best of them), but a modern audience has modern needs and sensibilities.

Practical Common Lisp at one time was the book for modern audiences, but even when it was released it fell short of what it should have been. It provides lots of practical projects, but doesn't provide a detailed guide for how to present those projects to the world. It's a book written for experienced programmers who are Lisp-curious and is partially meant to advocate for Lisp, but does little to fix the problem of Lisp's steep learning curve.

And it does have a steep learning curve. Why? Not really because of any feature of Common Lisp. The parentheses can be a bit challenging at first, but it's more of an emotional challenge than a technical one. Macros are tough to master, but not so hard to get started with. Common Lisp is a big language, but beginning is not particularly hard and searching the HyperSpec can go a long way to deepen your knowledge of the language.

No, it's not the language that's the source of the learning curve–it's Emacs. Emacs is the defacto-standard text editor for Common Lisp development. It's also 50 years old and doesn't have the mainstream popularity of other editors, creating a considerable mental block to even considering learning it or Common Lisp. On top of that, developers interact with Emacs very differently from how they interact with VSCode or the JetBrains IDEs (let alone OpenCode or Claude Code-like agentic LLM CLIs), hindering new users from transferring knowledge from the development environments they are familiar with.

Emacs is the elephant in the room that no books on Common Lisp address. PCL made a half-hearted attempt with Lisp in a Box (a distribution of Emacs somewhat analogous to the later Portacle, now deprecated), but it was insufficient to the task.

With this book I hope to provide you–the experienced Lisp-curious developer–with a source for learning both Common Lisp and Emacs at the same time, help you get oriented to the Lisp ecosystem and current practices, and get you deploying your applications in your preferred medium by the time you're finished reading.

1.1INTRODUCTION

ALMIGHTY

When you are given the job of choosing the tech stack for a job, how do you choose? If the task is data science, what language would you choose? Would your choice be different if your task was web development? Would it be different if it was embedded development? Or accounting? Or mobile apps?

Programming is fraught with choices. Probably the most important choice is which language to use for any particular task. If you're doing data analytics, you "need" to use Python. If you're developing a web application, you conventional wisdom says to use JavaScript, PHP, or Ruby. If you're writing accounting software, the "obvious" choice would be Java. If you're writing real-time software with performance and size limitations, "of course" you reach for C or Rust.

We take it for granted that such choices are necessary, that we need to choose a language based on a task. No language is adapted to every task; when you need to drill, you don't use a hammer.

But what if we had a special, universal tool? What if the tool could be adapted to the task, rather than chosen for it?

Common Lisp is just such a language. It's the highest level language out there thanks to macros and the parentheses, but a surprisingly low level language thanks to the ability to inspect generated assembly output and the ability to specify types (although in a somewhat sloppy way) to optimize for speed and memory efficiency. As a result, Lisp is both highly expressive while sacrificing little performance. The result is a highly adaptable language–perhaps the most adaptable.

Lisp does sacrifice something, though. Well-optimized C is going to yield smaller executables, lower memory use, and faster performance. Well written Ruby is probably aesthetically more pleasing than well written Lisp–and I believe that aesthetics are important. The Lisp ecosystem can usually get you started, but it's not going to do most of the heavy lifting like in Java.

With Lisp, you sacrifice choosing the absolute optimal tool for the job in exchange for absolute flexibility. Lisp may not initially be the best tool for any single job, but you can mould it into a very good tool for many jobs. It's not the fastest, but it's competitive with the fastest. It's not the prettiest, but you can make it prettier if that's important to you. There may not be a free library available to do exactly what you want, but you usually don't have to start from scratch, either.

Lisp is not a language specialized to a domain of work; it's a language specialized to being generally adaptable. It's not a master of any domain, but it can be adapted to a wide variety of domains.

In English, a man who isn't a specialist in any field, but who commands both knowledge and competency in many domains, is called a generalist.

In Japanese, such a man is called オールマイティ–almighty.

That's what Lisp is. Lisp is almighty, and it summons programmers to become almighty.

1.2INTRODUCTION

IS AI ALMIGHTY?

AI is a divisive topic among programmers. Some Lispers hate it, others love it.

But given that it exists, we have to decide our relationship with it. If you use AI, doesn't that at least theoretically boost your ability to be Almighty? I think so. I make use of it to do all kinds of tasks I otherwise would never attempt, such as writing the Emacs Lisp code I use to export this book's ORG file to multiple HTML files for the online version of this book (https://almightylisp.com), or the Typst code I use to generate the PDF version. On the other hand, most of this book was written by me, not by an LLM. It generated quick reference tables for me, and it wrote the chapter on loop because I didn't feel confident I could go into the detail that loop deserves. I used it to check for errors after I wrote this book (of which there were many).

I am also experimenting with using LLMs to build more complex systems with mixed results and feelings. None of those show up in this book. I'm still trying to form a solid opinion about it myself, like some of my handsome readers.

In some ways, I and many others feel pressured into using LLMs for fear of "being left behind". In other ways, it relieves the pressure to go on side-quests to learn how to set up servers for deploying, debug proxy server errors, etc.

On the other hand, if you overuse LLMs, you risk losing your ability to problem-solve or do any kind of valuable programming. This is especially the case if you haven't learned to the fundamental principles of programming (which necessarily requires practicing programming by hand). There are signs that some thought leaders are beginning to acknowledge the potential long-term risks of "tokenmaxxing".

My opinion as of now is that LLMs are a powerful tool that needs to be respected and used wisely. Wise use of LLMs necessarily requires that you have and maintain a knowledge of coding. LLMs are most valuable when skilled users are writing the prompts and checking the work.

In the context of Common Lisp programming, LLMs have one flaw: they won't spontaneously come up with sophisticated abstractions for expressing problems and solutions in novel ways. Coalton would never be spontaneously invented by an LLM to help solve hard math problems. My LLM was happy to use plain format strings to produce the HTML output for this book; I had to ask it to write and then use an HTML-generating domain specific language–it didn't come up with the idea on its own.

So being Almighty entails neither Tokenmaxxing nor shunning LLM use entirely. Almighty programmers respect LLMs' utility while acknowledging its weaknesses.