History, Implementations and Best Practices

55.1 History

Lisp and LISP 1.5 (McCarthy) MacLisp, Interlisp, Lisp Machine Lisp, Scheme

ARPA-sponsored effort to unify Lisp dialects begins *Common Lisp the Language* (CLtL1, Guy Steele)

X3J13 committee; CLOS designed (based on Flavors and CommonLoops) CLtL2 (second edition)

ANSI X3.226-1994: the Common Lisp standard; CLOS made it the first ANSI-standardized object-oriented language *The Art of the Metaobject Protocol* *On Lisp* (Graham) SBCL forks from CMUCL *Practical Common Lisp* (Seibel)

SBCL monthly releases, Coalton, Clasp, CLOG, ocicl, Lem, Nyxt, a revived community

55.2 Best Practices

✅ Develop interactively: compile one form at a time, test at the REPL, keep the image running.

✅ Organize code into packages and ASDF systems. Pin dependencies for applications.

✅ Use defparameter for configuration and defvar for state that should survive reloads.

✅ Write docstrings; use check-type and condition types for robust APIs.

✅ Use CLOS generic functions for extensible behavior and structures for simple fast records.

✅ Embrace the condition system: signal specific conditions, provide restarts in libraries, and decide policy at the top level.

✅ Measure before optimizing; add type declarations only in hot paths.

✅ Use Alexandria/Serapeum/UIOP instead of reinventing utilities.

✅ Write tests (FiveAM/Parachute) and run them in CI on more than one implementation.

❌ Mutating literal (quoted) data, or relying on destructive operations without using their results

❌ Using eval or intern on untrusted input; reading untrusted data with *read-eval* true

❌ Overusing macros where functions suffice; unhygienic macros that capture variables

❌ Global (safety 0): use it only locally in verified hot code

❌ Giant packages that :use many libraries (use package-local nicknames instead)

❌ Swallowing errors with broad ignore-errors