Lisp (historically LISP, an acronym for "LISt Processing") is a family of programming languages with a long history and a distinctive, fully parenthesized prefix notation. Originally specified in 1958 by John McCarthy, Lisp is the second‑oldest high‑level programming language after Fortran. It pioneered many concepts in computer science, including tree data structures, automatic storage management, dynamic typing, conditionals, higher‑order functions, recursion, and the self‑hosting compiler. Lisp dialects have evolved into numerous variants, most notably Common Lisp, Scheme, and Clojure, and remain influential in artificial intelligence, symbolic computation, and metaprogramming.

1 History

1.1 Origins (1958–1960)

1.1.1 McCarthy's original design

In 1958 John McCarthy, then at the Massachusetts Institute of Technology (MIT), conceived Lisp while working on algebraic list processing. The language was designed to operate on symbolic expressions (S‑expressions) rather than numbers, drawing on the lambda calculus of Alonzo Church and the concept of recursive functions. McCarthy published the seminal paper "Recursive Functions of Symbolic Expressions and Their Computation by Machine" in 1960, which laid the theoretical foundation.

1.1.2 First implementation on IBM 704

The first Lisp interpreter was implemented on an IBM 704 computer at MIT in 1958–1960. It was developed by McCarthy and his students (including Steve Russell, who realized that the universal function could be implemented as an interpreter). The IBM 704’s 36‑bit word and special features (such as the CAR and CDR instructions) directly influenced the representation of cons cells and list manipulation.

1.2 Early evolution (1960s–1970s)

1.2.1 MacLisp and Interlisp

During the 1960s and 1970s, two major dialects emerged: MacLisp (developed at MIT’s Project MAC) and Interlisp (originating at Bolt, Beranek and Newman and later Xerox PARC). MacLisp introduced many features now standard in Common Lisp, such as a compiler, arrays, and the Lisp machine. Interlisp was known for its integrated development environment (the “Interlisp programming environment”) and advanced debugging tools like the “break” package. These dialects influenced each other and competed during the formative years.

1.2.2 Lisp machines

By the mid‑1970s, specialized hardware called Lisp machines were developed to run Lisp efficiently. Companies such as Symbolics, Lisp Machines Inc. (LMI), and Xerox produced workstations with microcoded instruction sets tailored for Lisp operations. These machines featured high‑resolution displays, garbage‑collected memory, and powerful integrated development environments. The Lisp machine era peaked in the 1980s before general‑purpose workstations surpassed them.

1.3 Standardization and modern era (1980s–present)

1.3.1 Common Lisp (ANSI standard)

The proliferation of dialects led to a standardization effort in the early 1980s, aiming to unify MacLisp, Interlisp, and others into a common language. The resulting specification, Common Lisp, was first published in 1984 and later standardized by ANSI in 1994 (ANSI X3.226‑1994). Common Lisp is a large, multi‑paradigm language that includes an object system (CLOS), a powerful condition system, and an extensive set of standard functions. It remains the most widely used Lisp dialect for industrial and research applications.

1.3.2 Scheme and the minimalist tradition

Scheme, originally designed by Gerald J. Sussman and Guy L. Steele in 1975, took a different direction: minimalism and formal elegance. Scheme pioneered lexical scoping, continuations, and a unified treatment of data types. It became popular in computer science education and programming language research. Several standards exist, most notably the Revised Reports (RnRS), with R⁶RS (2007) and R⁷RS (2013) being the latest major versions.

1.3.3 Clojure and contemporary ecosystems

Rich Hickey created Clojure in 2007 as a modern Lisp that runs on the Java Virtual Machine (JVM), the Common Language Runtime (CLR), and JavaScript. Clojure emphasizes functional programming, immutable persistent data structures, and seamless interoperability with its host platforms. It has gained a strong following in web development, data analysis, and concurrent programming. Other contemporary Lisp dialects, such as Racket, Hy, and Janet, continue to explore different design niches.

2 Language features

2.1 Syntax and semantics

2.1.1 S‑expressions

Lisp’s syntax is built around S‑expressions (symbolic expressions). An S‑expression is either an atom (a number, symbol, or string) or a list of S‑expressions enclosed in parentheses. For example, (+ 1 2) is a list representing the addition of 1 and 2. This uniform syntax unifies code and data, making it easy to parse.

2.1.2 Homoiconicity

Lisp is homoiconic – the primary representation of a program is also a data structure (a list). This property allows Lisp programs to manipulate their own source code as ordinary data, facilitating metaprogramming and macros.

2.1.3 Macros

A macro is a function that transforms code at compile time (or read time). Lisp macros accept unevaluated S‑expressions and return new S‑expressions, which are then evaluated. This power enables users to extend the language syntax, define domain‑specific languages (DSLs), and optimize code without modifying the compiler.

2.2 Data types

2.2.1 Atoms and lists

The fundamental data structures are atoms (e.g., 42, 'foo) and lists (e.g., (a b c)). Lists are constructed from cons cells (also called pairs), where each cell holds two pointers: one to the element (car) and one to the rest of the list (cdr). The empty list, denoted NIL, also represents false.

2.2.2 Numbers, characters, and symbols

Lisp supports various numeric types: integers, rationals, floating‑point numbers, and complex numbers. Characters are self‑evaluating objects (e.g., #\A). Symbols are names used for variables and functions; they can have properties attached.

2.2.3 Vectors, hash tables, and structures

Beyond lists, Lisp dialects provide vectors (fixed‑size arrays), hash tables, and user‑defined structures (records). Common Lisp also offers arrays of arbitrary rank, adjustable arrays, and bit vectors.

2.3 Evaluation model

2.3.1 Lexical and dynamic scoping

Most modern Lisp dialects (Common Lisp, Scheme, Clojure) use lexical scoping by default, meaning variable bindings are resolved based on the program’s textual structure. Dynamic scoping, where bindings are looked up in the call stack, is also available in Common Lisp through special variables (declared with defvar or defparameter). Scheme originally used dynamic scoping but switched to lexical scoping in 1975.

2.3.2 First‑class functions and closures

Functions in Lisp are first‑class objects: they can be created dynamically, passed as arguments, returned from other functions, and stored in data structures. A closure is a function that captures the lexical environment in which it was defined. This feature is essential for functional programming and callbacks.

2.3.3 Condition system (Common Lisp)

Common Lisp’s condition system provides a flexible mechanism for signaling and handling exceptional situations (errors, warnings, etc.). Unlike simple exception handling, conditions allow the caller to restart from a known point, and handlers can choose among multiple restarts. This design supports error recovery without unwinding the stack.

2.4 Memory management

2.4.1 Garbage collection

Lisp was the first language to feature automatic memory management through garbage collection (GC). The original implementation used a simple mark‑and‑sweep collector. Modern dialects employ generational, incremental, or concurrent GC algorithms. Garbage collection frees the programmer from manual memory deallocation, reducing bugs.

2.4.2 Cons cells and list representation

Cons cells are allocated dynamically. A list such as (a b c) is represented as a chain of three cons cells: (a . (b . (c . NIL))). The dotted pair notation ((a . b)) is also used for pairs that are not proper lists. Efficient list processing relies on sharing of tail structures when possible.

3 Major dialects

3.1 Common Lisp

3.1.1 Object system (CLOS)

Common Lisp’s Common Lisp Object System (CLOS) is a powerful, dynamic object system that supports multiple inheritance, generic functions, and multiple dispatch (methods selected based on the types of all arguments). CLOS is integrated with the condition system and can be modified at runtime. It is defined as part of the ANSI standard.

3.1.2 Loop macro and condition handling

Common Lisp includes a comprehensive loop macro that provides a compact, declarative way to write iterative constructs (equivalent to for‑each, sum, collect, etc.). The condition handling (described in 2.3.3) is also a distinguishing feature.

3.2 Scheme

3.2.1 Minimalist design and continuations

Scheme is known for its small core and formal semantics. It introduced first‑class continuations (via call/cc), which represent the “remaining computation” at any point, enabling advanced control structures (coroutines, generators, exceptions). Scheme’s macro system (syntax-rules, syntax-case) is based on pattern matching and respects lexical scoping.

3.2.2 R⁷RS and R⁶RS standards

The Revised Reports have standardized Scheme over time. R⁶RS (2007) added a standard library, Unicode support, and a macro system. R⁷RS (2013) further modularized the language, dividing it into a small core and many optional libraries, and introduced a new syntax for records. However, Scheme remains fragmented, with many implementations (Racket, Guile, Chez Scheme) offering extensions.

3.3 Clojure

3.3.1 Hosted on JVM, CLR, and JavaScript

Clojure is a hosted language that compiles to the bytecode of the Java Virtual Machine (JVM), the Common Language Runtime (CLR), or JavaScript (via ClojureScript). It directly uses the host’s libraries and types, allowing seamless integration with existing ecosystems.

3.3.2 Persistent data structures and concurrency

Clojure provides persistent (immutable and structurally shared) data structures: lists, vectors, maps, and sets. Mutability is isolated through reference types (atoms, refs, agents) that use software transactional memory (STM) for coordinated changes. This design simplifies concurrent programming by eliminating many race conditions.

3.4 Historical dialects

3.4.1 Emacs Lisp

Emacs Lisp (Elisp) is the scripting language of the GNU Emacs editor. It is a dynamic, lexically‑scoped (since Emacs 24) Lisp dialect with a strong emphasis on text manipulation. Elisp code runs in the editor process and is used to extend Emacs functionality. It lacks many modern features (e.g., CLOS, strong numerical tower) but remains widely used.

3.4.2 AutoLISP

AutoLISP is a dialect used for customizing and automating Autodesk AutoCAD. It first appeared in 1986 with AutoCAD 2.18. AutoLISP provides access to the drawing database and can be used to create parametric designs. It is still supported in current versions of AutoCAD.

3.4.3 ISLISP

ISO Lisp (ISLISP) is a standardized dialect (ISO/IEC 13816) designed to be small and efficient, with a focus on portability. It includes a subset of Common Lisp features and a simple object system. ISLISP was developed in the 1990s but never achieved widespread adoption.

4 Programming paradigms

4.1 Functional programming

4.1.1 Immutability and side effects

Lisp dialects vary in their treatment of immutability. Scheme and Clojure encourage functional style, with persistent data structures and a preference for pure functions. Common Lisp allows mutation freely, but functional programming is possible by using let, lambda, and recursion without setf.

4.1.2 Recursion and tail‑call optimization

Recursion is a natural fit for Lisp dialects. Many implementations (especially Scheme, per the RnRS standard) perform tail‑call optimization (TCO), removing stack overflows for tail‑recursive functions. Common Lisp does not mandate TCO but many compilers support it via declarations.

4.2 Metaprogramming

4.2.1 Macros and code generation

Macros are the cornerstone of Lisp metaprogramming. They allow users to define new control structures (e.g., when, unless), domain‑specific languages (e.g., for parsing, web development), and compile‑time optimizations. Macros are expanded before evaluation, generating code that can be as efficient as hand‑written.

4.2.2 Read macros (reader macros)

Reader macros extend the Lisp reader itself. They allow custom syntactic constructs like ' (quote), ` ` (backquote), and ,` (unquote). Users can define new reader macros to support alternative syntax (e.g., regular expressions, XML literals). This is a more low‑level metaprogramming facility compared to ordinary macros.

4.3 Object‑oriented programming

4.3.1 CLOS and multiple dispatch

CLOS (see 3.1.1) is a full object system with multiple dispatch – generic functions are called on any combination of argument types, not just the first argument. Methods can be added, removed, and redefined at runtime. CLOS also supports method combination (e.g., :before, :after, :around).

4.3.2 Prototype‑based approaches in Scheme

Some Scheme implementations offer object systems, but the language itself has no built‑in OOP. Implementations like Racket have a class system, while others use closures to simulate objects. Scheme’s minimalism encourages exploring alternative paradigms.

4.4 Concurrent and parallel programming

4.4.1 Clojure’s agents and software transactional memory

Clojure provides agents for asynchronous, thread‑safe updates to mutable state, and software transactional memory (STM) for coordinated, optimistic concurrency using refs. These mechanisms prevent many concurrency bugs without explicit locking.

4.4.2 Common Lisp’s Bordeaux‑Threads

Common Lisp implementations often have their own threading libraries. Bordeaux‑Threads is a portable API providing threads, locks, condition variables, and atomics. It is widely used for parallel processing in Common Lisp.

5 Development tools and ecosystem

5.1 Integrated development environments

5.1.1 Emacs with SLIME/Sly

The de facto environment for Common Lisp development is Emacs with SLIME (Superior Lisp Interaction Mode for Emacs). SLIME provides a REPL, debugger, inspector, profiler, and cross‑reference. Sly is a fork of SLIME with a more modern user interface.

5.1.2 LispWorks and Allegro CL

Commercial IDEs exist for Common Lisp: LispWorks (with GUI builder, CAPI) and Allegro CL (with the Allegro Composer). These offer integrated debugging, code analysis, and deployment support.

5.2 Build systems and package managers

5.2.1 ASDF and Quicklisp (Common Lisp)

ASDF (Another System Definition Facility) is the standard build system for Common Lisp, managing compilation order and dependencies. Quicklisp is a library repository and package manager that downloads and installs ASDF systems automatically. It is maintained by Zach Beane.

5.2.2 Leiningen and deps.edn (Clojure)

Clojure projects commonly use Leiningen (a build tool with dependency management) or deps.edn (the Clojure CLI tool), which supports Maven repositories and Git dependencies.

5.3 Testing and debugging

Testing frameworks include FiveAM (Common Lisp), SRFI‑64 (Scheme), and clojure.test (Clojure). Debugging is aided by the interactive REPL, condition system restarts, and tracing capabilities (e.g., Common Lisp’s trace macro).

5.4 Documentation systems

Common Lisp code often includes docstrings, and tools like Hyperspec provide online reference. Lisp source files can include comments, and literate programming is supported via tools like Noweb. Clojure uses Marginalia and Codox for documentation generation.

6 Applications

6.1 Artificial intelligence and expert systems

6.1.1 Early AI projects (e.g., SHRDLU, MYCIN)

Lisp was the primary language for early AI research. SHRDLU (Terry Winograd, 1970) was a natural‑language understanding system that manipulated a block world. MYCIN (Edward Shortliffe, 1970s) was an expert system for diagnosing bacterial infections. Both were written in Lisp.

6.1.2 Symbolic AI and theorem proving

Symbolic reasoning, logic programming, and theorem provers (e.g., ACL2, Mizar in Lisp) have long used Lisp for its symbolic manipulation capabilities. The language’s flexibility made it ideal for prototyping inference engines.

6.2 Computer‑aided design and music

6.2.1 Autodesk AutoCAD’s AutoLISP

AutoLISP enables automation in AutoCAD, allowing designers to create parametric drawing scripts and custom commands. It is embedded in the AutoCAD environment and widely used in architectural and mechanical drafting.

6.2.2 Common Music and algorithmic composition

Common Music (by Heinrich Taube) is a Lisp‑based environment for algorithmic music composition. It supports sound synthesis, notation, and real‑time performance, leveraging Lisp’s symbolic processing for musical structure.

6.3 Web development and scripting

6.3.1 ClojureScript for front‑end

ClojureScript compiles Clojure to JavaScript, enabling functional front‑end development on the browser. Libraries like Reagent (React wrapper) and re‑frame provide modern single‑page application frameworks.

6.3.2 Hunchentoot and Caveman2 (Common Lisp)

Hunchentoot is a web server for Common Lisp, supporting HTTP/1.1, sessions, and AJAX. Caveman2 is a web framework that provides routing, templating, and middleware, inspired by Ruby’s Sinatra.

6.4 Education and programming language research

6.4.1 Structure and Interpretation of Computer Programs (SICP)

The textbook Structure and Interpretation of Computer Programs (Abelson & Sussman, 1985) uses Scheme to teach fundamental computer science concepts. It has been a cornerstone of MIT’s introductory programming course and influenced generations of programmers.

6.4.2 Teaching with Scheme

Scheme’s minimal syntax and rich semantics make it a popular teaching language for courses on programming languages, functional programming, and interpreters. Many universities use Racket, a Scheme dialect, in introductory CS curricula.

7 Community and culture

7.1 Influential figures

Key contributors include John McCarthy (creator), Guy L. Steele (Common Lisp, Scheme), Gerald J. Sussman (Scheme), Richard Stallman (Emacs Lisp), Rich Hickey (Clojure), and Kent Pitman (Common Lisp design). The community continues to honor these pioneers through conferences and archived writings.

7.2 Online forums and conferences

Lisp communities thrive on comp.lang.lisp (Usenet), r/lisp (Reddit), the Lisp subreddit, and the ClojureVerse forum. Major conferences include the International Lisp Conference (ILC), European Lisp Symposium (ELS), and Clojure/conj. The Lisp Games Jam (Lisp Game Jam) is an annual event for game development.

7.3 Humor and lore (e.g., Lisp in the AI winter)

Lisp culture embraces wit: the phrase “Lisp is a programmable programming language” is common. A well‑known joke states that “Lisp is the language that AI researchers use until they have to write a real program.” During the AI Winter (late 1980s–1990s), Lisp’s association with failed expert systems led to a decline in popularity, but enthusiasts continued to develop the language. The “Lisp Curse” refers to the tendency to rewrite everything from scratch due to the language’s power.

8 Future directions

8.1 Modernizing legacy systems

Many legacy Lisp systems (e.g., in finance, aerospace) remain in production. Efforts focus on porting them to modern hardware, integrating with contemporary build systems, and ensuring compatibility with new standards. Static analysis tools (e.g., SICL, Coalton) aim to improve safety and performance.

8.2 Interoperability with other languages

Lisp dialects increasingly emphasize foreign function interfaces (FFI) to call C, Java, Python, and Rust. Common Lisp’s CFFI (C Foreign Function Interface) and Clojure’s native interop are examples. The ability to reuse libraries from larger ecosystems helps Lisp remain relevant.

8.3 Lisp in the era of machine learning

While Python dominates machine learning, Lisp is making inroads with libraries like clml (Common Lisp Machine Learning) and Tech.io’s clj-ml (Clojure). Clojure’s scicloj community works on data‑science tooling. The homoiconic nature of Lisp could offer advantages in symbolic AI and differentiable programming, areas still active in research.