--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2018/07/a-road-to-common-lisp.markdown Wed Jul 25 22:32:23 2018 +0000
@@ -0,0 +1,664 @@
++++
+title = "A Road to Common Lisp"
+snip = "How I learned Lisp, and you can too."
+date = 2018-07-03T16:00:00Z
+draft = false
+
++++
+
+I've gotten a bunch of emails asking for advice on how to learn Common Lisp in
+the present day. I decided to write down all the advice I've been giving
+through email and social media posts in the hopes that someone might find it
+useful.
+
+<div id="toc"></div>
+
+## Context
+
+I think it's important to have a general sense of where Common Lisp came from
+and what kind of a language it is before you start learning it. There are a lot
+of things that will seem very strange if you're coming straight from modern
+languages, but will make a lot more sense if you've got a bit of background
+context.
+
+### History
+
+Lisp and Common Lisp have a long, deep history. I'm not going to try to cover
+it all here — if you're interested you should check out some of the following
+(in roughly increasing order of detail):
+
+* Wikipedia's [History of Lisp][wiki-history-lisp] and [History of Common Lisp][wiki-history-cl].
+* The [Where it Began section in Practical Common Lisp][pcl-history].
+* The [History: Where did Lisp come from?][cll-history] section of the comp.lang.lisp FAQ.
+* [Common Lisp: the Untold Story][untold] by Kent Pitman.
+* [The Evolution of Lisp][evolution] by Guy Steele and Richard Gabriel.
+
+I realize that you probably won't want to read all of the links above
+immediately, so here's a whirlwind tour of sixty years of Lisp.
+
+Lisp began in the late 1950's. It was invented by John McCarthy at MIT.
+
+Over the next twenty or so years various versions and dialects of Lisp grew and
+flourished. Some of the more notable dialects were Maclisp, BBN Lisp/Interlisp,
+Franz Lisp, Spice Lisp, and Lisp Machine Lisp. There were others too. The
+point is that there were a *lot* of different implementations, all growing,
+changing, and trying out different things.
+
+(Scheme also originated in this time frame, but took a very different route and
+diverged from the path we're looking at. I won't cover Scheme in this post.)
+
+In the early 1980s people decided that having a whole slew of
+mutually-incompatible dialects of Lisp might be not be the most desirable
+situation to be in. An effort was made to take these different languages that
+had grown organically and produce one common language that would satisfy the
+needs of everyone. In 1984 the first edition of Guy Steele's [Common Lisp: the
+Language][cltl] was published.
+
+If you do some math you'll see that at the time the book was published Lisp had
+around twenty-five years of real-world use, experimentation, experience, and
+history to draw upon. Even so, the book alone didn't quite satisfy everyone and
+in 1986 a committee (X3J13) was formed to produce an ANSI specification for
+Common Lisp.
+
+As the committee worked on the standardization process, in 1990 the second
+edition of Common Lisp: the Language was published. This was more comprehensive
+and contained some of the things the committee was working on (see the
+comp.lang.lisp FAQ linked above for more on this). At this point the Lisp
+family of languages had over 30 years of experience and history to draw upon.
+For comparison: Python (a "modern" language many people think of as also being
+"kind of old") [was released][python] for the first time the following year.
+
+In 1992 the X3J13 published the first draft of the new ANSI standard for Common
+Lisp for public review (see Pitman's paper). The draft was approved in 1994 and
+the approved specification was finally published in 1995. At this point Lisp is
+over thirty-five years old. The first version of Ruby [was released][rubby] in
+December of that year.
+
+That's the end of the history lesson. There has not been another revision of
+the ANSI specification of Common Lisp. The version published in 1995 is the one
+that is still used today — if you see something calling itself "an
+implementation of Common Lisp" today, that is the specification it's referring
+to.
+
+### Consequences
+
+So why am I telling you all this? Because I want you to know what you're
+getting yourself into. I want you to realize that Common Lisp is a stable,
+large, practical, extensible, ugly language. Understanding these
+characteristics will make a lot of things make more sense as you learn the
+language.
+
+#### Escaping the Hamster Wheel of Backwards Incompatibility
+
+If you're coming from other languages, you're probably used to things breaking.
+If you want to run Ruby code written ten years ago on the latest version of
+Ruby, it's probably going to take some time to update it. My current day job is
+in Scala, and if a library's last activity is more than 2 or 3 years old on
+Github I just assume it won't work without a significant amount of screwing
+around on my part. The hamster wheel of backwards incompatibility we deal with
+every day is a fact of life in most modern languages (though some are certainly
+better than others).
+
+If you learn Common Lisp, this is not the case. In the next section of this
+post I'll be recommending a book written in 1990. You can run its code,
+unchanged, in a Common Lisp implementation released last month. After years of
+jogging on the hamster wheel of backwards incompatibility I cannot tell you how
+much of a relief it is to be able to write code and reasonably expect it to
+still work in twenty years.
+
+Of course, this is only the case for the language itself — if you depend on any
+libraries there's always the chance they might break when you update them. But
+I've found the stability of the core language is contagious, and the Common Lisp
+community seems overall fairly good about maintaining backwards compatibility.
+I'll be honest though: there are exceptions. As you learn the language and
+start using libraries you'll start noticing some library authors who don't
+bother to document and/or preserve stable APIs for their libraries, and if
+staying off the hamster wheel is important to you you'll learn to avoid relying
+on code written by those people as much as possible.
+
+This may sound a little bleak, but it's made a bit better by some other
+characteristics of Common Lisp: it's a large, practical language. The second
+edition of Common Lisp: the Language (usually abbreviated as "CLtL2" by Common
+Lisp programmers) is 971 pages long, not including the preface, references, or
+index. When programming in Common Lisp people will tend to depend on
+a small(ish) number of libraries, and library writers often try to minimize
+dependencies by utilizing as much of the (large) core language as possible.
+I personally try to stick to fewer than ten or so dependencies for my
+applications and no more than two or three for my libraries, but I'm probably
+a bit more conservative here than most folks (I *really* don't like the hamster
+wheel any more).
+
+It's also worth noting that since Common Lisp has been around and stable for so
+long, it has *libraries* older and more stable than many programming languages.
+For example: Bordeaux Threads (the de-facto threading library for Common Lisp)
+was first proposed in 2004 and released soon after (2006 at the latest but
+possibly earlier, it's hard to tell because so many links are dead now), which
+makes it fourteen years old. So yes, threading is handled by a library, but I'm
+not worried about it breaking my code in the next decade or two.
+
+As you learn Common Lisp and look for libraries, try to suppress the voice in
+the back of your head that says "This project was last updated six years ago?
+That's probably abandoned and broken." The stability of Common Lisp means that
+sometimes libraries can just be *done*, not *abandoned*, so don't dismiss them
+out of hand.
+
+#### Power
+
+Part of Common Lisp's practicality comes from its extensibility. No one has
+been clamoring for a new version of the specification that adds features because
+Common Lisp gives users enough power to add new features to the language as
+libraries without having to alter the core language.
+
+Macros are what might come to mind when you hear "Lisp extensibility", and of
+course that's part of it. Macros allow users to write libraries that would need
+to be core language features in other languages.
+
+Common Lisp doesn't include string interpolation. You want it? No problem, you
+don't have to wait for [Scala
+2.10](https://docs.scala-lang.org/overviews/core/string-interpolation.html) or
+[Python 3.6](https://www.python.org/dev/peps/pep-0498/), just [use
+a library][cl-interpol].
+
+Want to try some nondeterministic programming without any boilerplate? [Grab
+a library][screamer].
+
+Pattern matching syntax can make for some really beautiful, readable code.
+Common Lisp doesn't include it, but of course [there's a library][trivia].
+
+Enjoying algebraic data types in Haskell or Scala? Here's your [library][cl-adt].
+
+All of these libraries rely on macros to make using them feel seamless. Of
+course you could *do* all of that without macros, but you've have to add a layer
+of boilerplate to manage evaluation. This:
+
+ (match foo
+ '(list x y z) (lambda (x y z) (+ x y z))
+ '(vector x y) (lambda (x y) (- x y)))
+
+just doesn't flow off the fingers like:
+
+ (match foo
+ ((list x y z) (+ x y z))
+ ((vector x y) (- x y)))
+
+No one's up in arms trying to get a new revision of the Common Lisp standard to
+add pattern matching because you can write it as a library and get 95% or more
+of what you've get if it were built in. The language gives you enough power to
+extend it in a way that feels like the extension was there from the beginning.
+
+Macros are one of the things that make Lisp so incredibly extensible, because
+they let you transform arbitrary code into other arbitrary code. This is true
+for macros in languages like C too, but Common Lisp macros are fundamentally
+different because they're *part of the language*.
+
+In C you have a layer of macros on top, written in a separate preprocessor macro
+language. The macro layer and the language layer are separate from each other,
+with the macro layer providing one one extra level of abstractive power.
+
+In Common Lisp, you write macros *in Common Lisp itself*. You can then use
+those macros to write functions, and use those functions to write more macros.
+Instead of two stratified layers it's a *feedback loop* of abstractive power.
+
+But macros aren't the only thing about Common Lisp that make it so practical and
+extensible. Something that people often don't realize is that while Common Lisp
+is an extremely high-level language thanks to macros, it also has plenty of
+low-level facilities as part of the language. It's never going to be as
+low-level as something like C or Rust, but you might be surprised at some of the
+things that the ANSI spec includes.
+
+Want to see the assembly that a particular function compiles down to?
+[`DISASSEMBLE`][dis] it!
+
+Want to stack-allocate something to avoid some garbage collection? X3J13
+[thought of that][dynext].
+
+Need arrays of unboxed floats to ship to a graphics card? [The standard allows
+for that][arrays].
+
+Think `GOTO` should be considered helpful, not harmful? Well okay, we're all
+adults here. [Good luck][tagbody], try not to shoot your foot off.
+
+Need to do unsigned 8-bit arithmetic in your Game Boy emulator, but would prefer
+it to compile down to just a machine instruction or two? [It's
+possible][arith].
+
+Not all Common Lisp implementations actually perform all these optimizations,
+but the designers of Common Lisp had the foresight to include the language
+features needed to support them. You can write vanilla Common Lisp as defined
+by the standard and trust that it will run everywhere, and implementations that
+*do* support these kinds of things will take advantage of the optimization
+opportunities.
+
+This combination of supporting extremely high-level programming with macros and
+a reasonable amount of low-level optimization mean that even though the
+specification is over twenty years old, it's still a good solid base to build on
+today. The thirty years of experience and history the designers were drawing
+from allowed them to create a very practical language that has survived for
+decades.
+
+#### Ugliness
+
+It's also important to realize that while Common Lisp might be incredibly
+practical, the need to accommodate existing users and dialects means that there
+are ugly parts. If you buy a paper copy of the second edition of Common Lisp:
+the Language and look up "kludges" in the index you'll find this:
+
+[![Photo of a page of CLtL2's Index, listing "kludges" as pages 1 to 971](/media/images/blog/2018/07/lisp-kludge.jpeg)](/media/images/blog/2018/07/lisp-kludge.jpeg)
+
+Common Lisp is not a beautiful crystal of programming language design. It's
+a scruffy workshop with a big pegboard wall of tools, a thin layer of sawdust on
+the floor, a filing cabinet in the office with a couple of drawers that open
+perpendicular to the rest, and there's a weird looking saw with `RPLACD` written
+on the side sitting off in a corner where no one's touched it for twenty years.
+
+This historical baggage is a price paid to ensure Common Lisp had a future. It
+made it practical for people using the old dialects to actually adopt Common
+Lisp with a reasonable amount of effort. If the designers had tried to make it
+perfect and beautiful the language probably would have been ignored as too
+different to port implementations and code to, instead of being adopted and
+embraced.
+
+[wiki-history-cl]: https://en.wikipedia.org/wiki/Common_Lisp#History
+[wiki-history-lisp]: https://en.wikipedia.org/wiki/Lisp_(programming_language)#History
+[cll-history]: https://www.cs.cmu.edu/Groups//AI/lang/lisp/faq/lisp_2.faq
+[pcl-history]: http://www.gigamonkeys.com/book/introduction-why-lisp.html#where-it-began
+[untold]: http://www.nhplace.com/kent/Papers/cl-untold-story.html
+[evolution]: https://www.dreamsongs.com/Files/HOPL2-Uncut.pdf
+[cltl]: https://www.cs.cmu.edu/Groups/AI/html/cltl/cltl2.html
+[python]: https://en.wikipedia.org/wiki/History_of_Python#Early_history
+[rubby]: https://en.wikipedia.org/wiki/Ruby_(programming_language)#First_publication
+[bt-release]: https://web.archive.org/web/20040831185622/http://ww.telent.net/diary/2004/7/#9.57181
+[cl-interpol]: https://edicl.github.io/cl-interpol/
+[screamer]: https://nikodemus.github.io/screamer/
+[trivia]: https://github.com/guicho271828/trivia/wiki/What-is-pattern-matching%3F-Benefits%3F
+[cl-adt]: https://github.com/tarballs-are-good/cl-algebraic-data-type
+[dis]: http://clhs.lisp.se/Body/f_disass.htm
+[dynext]: http://clhs.lisp.se/Body/d_dynami.htm
+[arrays]: http://clhs.lisp.se/Body/15_ab.htm
+[arith]: https://pdfs.semanticscholar.org/7089/0eff0e93aba49174a9346731f4bf9225706d.pdf
+[tagbody]: http://clhs.lisp.se/Body/s_tagbod.htm
+
+## A Road to Learning Common Lisp
+
+If all of this hasn't scared you away from the language, let's talk about how
+you can learn it in 2018.
+
+If you search around on the internet for Common Lisp tutorials and guides,
+you're not going to find as much as you might expect. This is because a lot of
+Common Lisp reference material was created before and/or during the infancy of
+the internet. There are a *lot* of books about Common Lisp out there. Some are
+better than others. I'll recommend the ones I personally think are the best,
+but don't hesitate to browse around and find others.
+
+One final disclaimer: this is *a* road to Common Lisp, not *the* road to Common
+Lisp. It's what I followed (without some of the dead ends) and has a lot of my
+personal opinions baked in, but is by no means the only way to learn the
+language. Ask around and get some more opinions — more options won't hurt!
+
+### Get a Lisp
+
+To get started with Common Lisp you'll need to install a Common Lisp
+implementation. Remember: Common Lisp is an ANSI specification, so there are
+multiple implementations of it, which gives you choices. There are a bunch of
+options, but I'll make it simple for you:
+
+* If you're comfortable with the command line, installing packages with a package manager, and already have a text editor you like, choose [SBCL][].
+* Otherwise, choose [ClozureCL][CCL] (often called "CCL").
+
+That's Clozure with a Z. Clojure is something entirely different that just
+happens to have a confusingly similar name.
+
+You might also hear of something called CLISP, which sounds like it might be
+what you want. It's not. CLISP is just another implementation, but it hasn't
+had a release in eight years (even though development is still ongoing in its
+source repos) and it's not as commonly used as CCL or SBCL, so it'll be harder
+to find help if you have questions about the installation, etc.
+
+You might also hear about something called Roswell. Don't use Roswell, you don't
+need it (yet (or at all)).
+
+Just install SBCL or CCL for now, you can explore the other options once you've
+got your bearings a bit better.
+
+### Pick an Editor
+
+You might hear people tell you that you *must* learn Emacs before learning
+Common Lisp. They're wrong. You can get started learning the language just
+fine in whatever text editor you're comfortable in.
+
+If you don't have a preference, CCL itself comes bundled with a text editor on
+MacOS. That one will work just fine to start.
+
+Emacs, Vim, Sublime Text, Atom, whatever, for now it doesn't matter. As long as
+it can balance parenthesis and highlight comments and strings, that's all you
+need to start. Worry about shaving the editor yak once you're more comfortable
+in the language.
+
+### Hello, Lisp
+
+To check that you've got everything set up properly, make a `hello.lisp` file
+with the following contents:
+
+ :::lisp
+ (defun hello ()
+ (write-line "What is your name?")
+ (let ((name (read-line)))
+ (format t "Hello, ~A.~%" name)))
+
+Don't worry about what this means yet, it's just a check that everything's
+working properly.
+
+Open an SBCL or CCL REPL and load the file by entering `(load "hello.lisp")`,
+then call the function and make sure it works. It should look something like
+this if you picked SBCL:
+
+ $ sbcl
+ * (load "hello.lisp")
+
+ T
+ * (hello)
+ What is your name?
+ Steve
+ Hello, Steve.
+ NIL
+ *
+
+Or this if you chose CCL (the program might be annoyingly named `ccl64` if
+you're on a 64-bit system):
+
+ $ ccl64
+ Clozure Common Lisp Version ...
+
+ ? (load "hello.lisp")
+ #P"/home/sjl/Desktop/hello.lisp"
+ ? (hello)
+ What is your name?
+ Steve
+ Hello, Steve.
+ NIL
+ ?
+
+If your arrow keys and backspace don't work in the REPL, use [`rlwrap`][rlwrap]
+to fix that. `rlwrap sbcl` will give you a non-miserable REPL. `rlwrap` is
+a handy tool to have in your toolbox anyway.
+
+[rlwrap]: https://github.com/hanslub42/rlwrap
+
+### A Gentle Introduction
+
+The best book I've found for getting started in Common Lisp is [Common Lisp:
+A Gentle Introduction to Symbolic Computation][book-gentle]. This book really
+does strive to be gentle. Even if you've programmed before I'd recommend
+starting here because it eases you into the language. If you find it's moving
+too slow just skim forward a bit.
+
+The 1990 edition is available free from the site, and there's a 2013 reprint
+which fixes some minor errors in the 1990 version. If you can afford it I'd
+recommend buying the 2013 edition, but the 1990 version will also do fine.
+
+Go through the book and *do all the exercises*. This will take a while.
+
+This is mainly meant to get you started overcoming some of the main obstacles to
+being comfortable in Common Lisp, like:
+
+* How am I ever going to remember all these weird function names?
+* Why do people use strings so rarely?
+* When do I need/not need the goddamned quotation mark?
+
+You should also join the `#clnoobs` channel on Freenode so you can ask questions
+if you get stuck. For the most part people there are friendly and helpful,
+though I'll warn you in advance that there's at least one person who can
+sometimes be abrasive.
+
+If IRC isn't your thing there's also a [Discord
+server](https://discord.gg/tffeu2x) that some of us hang out in. Join the
+`#common-lisp` channel there and we'll be happy to help you.
+
+[book-gentle]: https://www.cs.cmu.edu/~dst/LispBook/
+[SBCL]: http://www.sbcl.org/on
+[CCL]: https://ccl.clozure.com/
+
+### Getting Practical
+
+Once you've finished that book the next one you should attack is [Practical
+Common Lisp][book-pcl]. You can get a paper copy if you want, but the full book
+is available on the site.
+
+You can skip the editor/programming environment part because the environment it
+recommends (Lisp in a Box) is abandoned and no longer works. Just keep using
+the programming environment you're comfortable with for now.
+
+Unfortunately the book doesn't include exercises. If you *really* want to get
+the most out of it you can type in all the code as you're reading it and poke at
+it, but if you've already done the exercises in the previous book it's probably
+safe to just sit down and read the book carefully.
+
+Make sure you understand everything as you go through the book. Don't be afraid
+to ask questions on IRC or Discord (or email me if you want, I don't mind) if
+something's not clear.
+
+You should also begin to get comfortable looking up things in [the Common Lisp
+language specification][clhs] itself. It's the ultimate manual for Common Lisp.
+It can be pretty dense at points, but can answer many questions you might have.
+You can either use the index page to find what you're looking for or just search
+on Google for "clhs whatever". CLHS stands for "Common Lisp HyperSpec", which
+is the hyperlinked, HTML version of the spec.
+
+(Some people will tell you to learn the language by just reading the spec. That's
+ridiculous — it's like trying to learn French by reading a dictionary. It's
+a useful tool to have, but not the only one you'll need.)
+
+[book-pcl]: http://www.gigamonkeys.com/book/
+[clhs]: http://www.lispworks.com/documentation/lw70/CLHS/Front/Contents.htm
+
+### Make Something
+
+Once you've got those two books under your belt and some practice using the
+spec, it's time to make something without someone holding your hand. It doesn't
+have to be anything big or special, the goal is to just write some Lisp without
+having the answer on the next page.
+
+If you need some ideas:
+
+* Do some [Project Euler](https://projecteuler.net/) problems.
+* Do some [Advent of Code](https://adventofcode.com/) exercises.
+* Make a [stupid Twitter bot](https://twitter.com/git_commands).
+* Make a personal calendar program that records your appointments, checks the
+ weather forecast the day of, etc.
+
+It doesn't really matter what you make, just make *something* on your own.
+
+### Lisp as a System
+
+At this point it's time to take your Common Lisp skills up a notch. Up until
+now I've told you to just use any text editor because it's more important to get
+you some experience with the language, but now it's time to move on.
+
+In most languages the development process looks something like this:
+
+1. Edit some code in the project with an editor.
+2. Compile the project (some languages skip this step).
+3. Run the project (or the tests).
+4. Observe the output (in the console, a browser, etc).
+5. Go to 1.
+
+This is not how most Common Lisp users interact with the language. In Common
+Lisp, the development cycle looks more like this:
+
+1. Start a Lisp process.
+2. Load the project.
+3. Edit some code with your editor.
+4. Tell the running process to compile *only the code you edited*.
+5. Interact with the changed code in the process via the REPL, an HTTP request, etc.
+6. Observe the output (either in the console, a browser, etc).
+7. Go to 3.
+
+When you embrace the Lisp way of working you'll rarely recompile and reload an
+entire project. Usually you'll write a function (or a macro, or parameter, or
+whatever), compile just that function, maybe poke at it in the REPL a bit, and
+then move on to the next function. This has some advantages over the
+traditional compile-everything-then-run approach.
+
+First: compiling a small chunk of code is fast. I just timed compiling a few of
+the larger functions in one of my projects and they took around 50-80
+microseconds. You don't have to wait for the compiler, so your
+concentration/thought process never has time to wander.
+
+Another advantage is that when you get back the results of your compilation,
+any errors or warnings you receive are almost certainly related to the few
+lines of code you just compiled. If you compile a ten-line function, run it,
+and get a division by zero error you can immediately focus in on the ten lines
+you just compiled and think about what changed.
+
+Because the Lisp process is always running, as soon as you compile a function
+it's ready to be used in the REPL. You can throw some arbitrary data at it and
+inspect the results to see how it behaves in isolation before you build more
+things on top of it.
+
+This cycle of making a function, compiling it, poking at it to make sure it's
+working as expected, and moving on happens constantly.
+
+In contrast, when working in languages like Scala or Python I almost never find
+myself writing one single function and compiling or running the project
+immediately. Spinning up the compiler or running the unit tests takes at
+*least* a second or two (or, sometimes *minutes* in Scala, unfortunately) so to
+avoid having a constant stream of gaps in my thought I end up writing a bunch of
+functions at once, and then run the project or tests once I know they have
+a chance of working.
+
+But then when I get back an error I have much more surface area to check,
+because I've added a lot of new code! So now I have to track down a problem
+that might be in something I wrote four minutes ago, whereas in Lisp I would
+only have to ever look at the code I wrote in the last few seconds.
+
+I've started using IntelliJ with Scala to help make this a bit less painful. It
+does help with the compile times because it recompiles things on the fly, but it
+doesn't solve the rest of the problem. I can write a Scala function in IntelliJ
+and it will be compiled immediately, but I can't *interact* with it immediately
+like I can in Common Lisp.
+
+When you work in this style with Common Lisp I think you'll really grow to love
+it. Writing in other languages will begin to feel like shipping your code off
+to the DMV and getting it back a week with a page full of red ink somewhere in
+the hundred forms you filled out. Writing in Common Lisp feels like interacting
+with a living, breathing organism, or like [teaching things to an eager
+assistant][eager].
+
+This goes beyond just the short feedback loop and interactive REPL, too. As an
+example, imagine you're making a video game and have a bug somewhere in your
+damage calculation that will occasionally cause a division by zero. Now let's
+say you're working on the code for a particular quest. You'll start the game,
+load a save file at the beginning of the quest, and start going through the
+steps. All of a sudden, in the middle of killing the final monster for the
+quest, you hit the damage bug! In tradition languages, one of two things might
+happen:
+
+1. The game crashes, and you get a stack trace and maybe a core dump.
+2. You've wrapped a `try` block around the main game loop that logs a stack
+ trace and ignores errors and allows the game to continue.
+
+Case 1 is pretty bad. You've got to try to track down the bug from a snapshot
+of what things looked like at the time (the stack trace and core dump). And
+even if you manage to fix it, now you've got to redo all that playing to get
+back to testing your quest code that you were originally working on.
+
+Case 2 is bad, in a different way. If you just ignore errors all the time, the
+game might now be in a weird state. You also might lose some critical context
+that's necessary to debug the problem, unless you're also saving a core dump
+(but I don't know of many people who do that).
+
+In Common Lisp you can certainly choose to panic or ignore on errors, but
+there's a better way to work. When an error is signaled in Common Lisp, it
+doesn't unwind the stack. The Lisp process will pause execution at that point
+and open a window in your editor showing you the stack trace. Your warrior's
+sword is hovering at the monster, waiting for you. At this point you can
+communicate with the running process at the REPL to see what's going on. You
+can examine variables in the stack.
+
+Once you figure out the problem ("Oh, I see, the `calculate-armor-percentage`
+function returns `0` if a shielding spell ran out during the same frame") you
+can fix the code, recompile the problematic function, and *restart the execution
+of that function in call the stack*. Your warrior's sword lands, and you move
+back to what you were doing before.
+
+You don't have to track down the bug from just a stack trace, like a detective
+trying to piece together what happened by the blood stains on the wall. You can
+examine the crime *as it's happening* and intervene to save the victim. It's
+like if you could run your code in a debugger with a breakpoint at every single
+line.
+
+Maybe you don't make video games. But this process can be useful in call kinds
+of contexts. Maybe you're writing a web app that talks to an API somewhere, and
+are debugging a requests that fails somewhere between two calls to the API,
+maybe "create widget `foo`" and "add `foo` to widget list `bar`". Instead of
+just aborting the request, logging a stack trace, and now leaving things in
+a possibly weird state (`foo` having been created without being in the expected `bar`
+list), you can fix the problem and allow the request to finish properly.
+
+Of course this won't always work. If you've got a big function that does some
+side effects and then crashes, restarting execution of the function would make
+the side effects happen again. But if you divide up your functions well ([one
+function to a function][1ftaf]) this case is pretty rare. And even when it does
+happen, it just means you're back in the same situation you're in *by default*
+with other languages!
+
+[eager]: https://www.reddit.com/r/lisp/comments/4oo1cp/common_lisp_for_clojure_programmer/d4eec68/
+[1ftaf]: https://groups.google.com/forum/message/raw?msg=comp.lang.lisp/9SKZ5YJUmBg/Fj05OZQomzIJ
+
+### Learning Paradigms
+
+### Recipes for Success
+
+## Where to Go From Here
+
+### Macros
+### Object-Oriented Programming with CLOS
+### Low-Level Programming
+### Web Development
+### Game Development
+### Window Management
+### Unit Testing
+
+## Modern Common Lisp
+
+### Structure and Building
+
+#### Packages
+#### Systems
+#### Projects
+#### Naming Conventions
+
+### Common/Important Libraries
+
+[Alexandria][alexandria]
+[Drakma][]
+[Bordeaux Threads][bt]
+[Flexi Streams][flexi]
+[Gray Streams][gray]
+[Iterate][iterate]
+[local-time][]
+[lparallel][]
+[named-readtables][]
+[CL-PPCRE][ppcre]
+[Roswell][]
+[SERIES][series]
+Trivial-whatever
+[uiop][]
+[usocket][]
+
+[alexandria]: https://common-lisp.net/project/alexandria/
+[iterate]: https://common-lisp.net/project/iterate/
+[series]: https://www.cliki.net/Series
+[bt]: https://common-lisp.net/project/bordeaux-threads/
+[gray]: https://www.cliki.net/Gray%20streams
+[flexi]: https://edicl.github.io/flexi-streams/
+[ppcre]: https://edicl.github.io/cl-ppcre/
+[uiop]: https://www.cliki.net/UIOP
+[usocket]: https://common-lisp.net/project/usocket/
+[drakma]: https://edicl.github.io/drakma/
+[lparallel]: https://lparallel.org/
+[local-time]: https://common-lisp.net/project/local-time/
+[named-readtables]: https://github.com/melisgl/named-readtables
+[Roswell]: https://github.com/roswell/roswell
+
+