Chapter 13: The List Processor
Cast of characters
| Name | Lifespan | Role |
|---|---|---|
| John McCarthy | 1927–2011 | Author of the 1958 MIT AI Memo No. 1, the 1960 CACM paper, and most of the LISP 1.5 manual. Brought the Dartmouth naming agenda into MIT’s symbolic-language design. |
| Steve Russell | — | Early LISP implementer credited, with Daniel Edwards, in the LISP 1.5 manual’s interpreter lineage. |
| Daniel J. Edwards | — | Early interpreter implementer with Russell; LISP 1.5 manual co-author. |
| Timothy P. Hart | — | LISP 1.5 manual co-author and compiler contributor. |
| Michael I. Levin | — | LISP 1.5 manual co-author; prepared the manual for publication and authored Appendix B. |
| Paul W. Abrahams | — | LISP 1.5 manual co-author. |
Timeline (1958–1962)
timeline title LISP from memo to manual, 1958–1962 September 1958 : MIT AI Project Memo No. 1, "An Algebraic Language for the Manipulation of Symbolic Expressions" : FLPL limits, S-expressions and M-expressions, recursive functions, IBM 704 representation 1958–1959 : Russell and Edwards implement the early LISP interpreter on the IBM 704 (per LISP 1.5 manual p. 4) March 1959 : MIT AI Project Memo No. 8, "The LISP Programming System" April 1960 : "Recursive Functions of Symbolic Expressions and Their Computation by Machine, Part I" in Communications of the ACM 3(4) 1962 : LISP 1.5 Programmer's Manual published by MIT Press — consolidating language definition, garbage collection, READ/EVAL/PRINT cycle, and macrosPlain-words glossary
- S-expression — A symbolic expression written either as an atom (a name like
X) or as a parenthesised list of symbolic expressions (e.g.(A B C)or(LAMBDA (X) (CAR X))). The data structure LISP programs read, write, and execute. Identical in form to LISP source code, which is what makes the language self-modifying. - M-expression — McCarthy’s original intended external syntax: a more conventional algebraic notation (e.g.
car[x]) that programmers would write, and that would translate into S-expression data. M-expressions were largely planned but never adopted; users wrote S-expressions directly, and the irony stuck. car/cdr/cons— The three basic LISP cell operations.carreturns the head of a list;cdrreturns the rest;consbuilds a new pair from a head and a tail. The names preserve the IBM 704 machinery beneath the mathematical notation.eval— A function that takes a symbolic expression representing a LISP form and runs it, returning the value. The hinge that turned LISP from notation into a running language.- Lambda / recursive functions — A way of describing functions anonymously and applying them to data, lifted from Church’s lambda calculus. Recursive function definitions are the natural control structure when programs work over symbolic structures of unknown depth.
cond— LISP’s primitive conditional: a list of test–result pairs, evaluated left to right until a test succeeds. The first general conditional expression to take both its branches as ordinary symbolic data.- Garbage collection / free-storage list — The runtime discipline of automatically reclaiming list cells that are no longer referenced. The LISP 1.5 manual lays it out as language infrastructure; garbage collection is what makes symbolic programs feel native rather than hand-managed.
Chapter 13: The List Processor
Section titled “Chapter 13: The List Processor”LISP was both theory and tool. McCarthy’s 1958 memo was groundwork, not the whole system; what emerged was a staged convergence of notation, machine representation, interpreter, memory discipline, and research habit.
The boundary is IPL. Logic Theorist and GPS already had list-processing infrastructure. LISP’s force was different: it made symbolic notation, symbolic data, and symbolic programs share one medium.
IPL before LISP, FLPL before LISP Proper
Section titled “IPL before LISP, FLPL before LISP Proper”The safest way to begin LISP is not with LISP. It is with the work already around it.
Newell, Shaw, and Simon’s work on Logic Theorist and GPS already depended on IPL, a language family built for list structures and symbolic routines. Chapter 12 owns that line: theorem lists, problem lists, working memories, and means-ends machinery. By the time McCarthy’s MIT work took shape, list processing was already a live technique in AI, not a blank space waiting for a name.
That order keeps the origin story honest.
This matters.
Second, LISP did not appear detached from FORTRAN-era programming practice. McCarthy’s September 1958 MIT AI Memo No. 1 began from a detour called FLPL, a FORTRAN-based list-processing language developed in the IBM orbit with Herbert Gelernter. That origin is important because it puts the language inside a specific tension. FORTRAN was a triumph for numerical computation. It made algebraic-looking formulas practical on machines like the IBM 704. But symbolic AI did not mainly want to compute floating-point trajectories or engineering tables. It wanted to manipulate expressions, logical sentences, substitution structures, and trees.
McCarthy’s broader commonsense-reasoning agenda sharpened that need. The Advice Taker idea, developed in the same late-1950s period, required a way for a program to represent propositions and operate over them. A sentence about the world had to be data; a rule for transforming that sentence had to be data too; and the program had to inspect both without forcing everything into numerical arrays. The problem was not merely syntax. It was representation.
That is why FLPL is such a useful starting point. A FORTRAN-based extension could demonstrate that list processing on existing hardware was not fantasy. But it also exposed a mismatch between numerical-programming conventions and McCarthy’s target. A language for commonsense reasoning had to make symbolic expressions ordinary objects. It had to let functions take them apart, build new ones, and express tests over their shape. That was a stronger requirement than giving FORTRAN a few list-handling subroutines.
The IBM 704 is part of that story, not scenery. The machine had been designed for serious numerical work, and the programming culture around FORTRAN did not naturally put symbolic manipulation at the center. Yet McCarthy’s symbolic language work targeted that very hardware. LISP’s later mathematical elegance was built out of machine compromises: words, addresses, decrement fields, and lists laid across memory cells.
Even the names car and cdr carry the machine inside them. They were not arbitrary bits of mathematical whimsy. car came from the Contents of Address Register operation, and cdr from the Contents of Decrement Register operation on the IBM 704. A LISP list cell was a pair, and the IBM 704 word made that pair feel natural. On another architecture, the surface names and storage story might have looked different.
So the first layer of LISP is a refusal. FLPL showed that a FORTRAN-based route was possible but cramped. IPL showed that list processing was already real but tied to a different symbolic-programming lineage. McCarthy’s path at MIT tried to assemble a more general algebraic language for symbolic expressions: not just routines that happened to process lists, but a language in which the lists, the expressions, and the functions over them could be stated together.
The chronology matters. AIM-001 in 1958 did not deliver the final LISP 1.5 environment. The 1960 CACM paper gave the recursive-functions presentation a canonical public form. The 1962 manual consolidated a usable system with named implementers, storage management, console behavior, and extension mechanisms. Treating those moments as one event erases the actual engineering work by which theory became a research tool.
List Structure and Symbolic Expressions
Section titled “List Structure and Symbolic Expressions”The central object in the 1958 memo and the 1962 LISP 1.5 manual is the symbolic expression, or S-expression. The point was not to make a prettier notation for numbers. It was to give symbolic AI a physical and formal object small enough for a machine and general enough for reasoning.
An S-expression could be an atom or a pair. Atoms were indivisible symbols, such as names or identifiers. Pairs joined two expressions into a dotted pair. From pairs, lists followed: a list was a chain of pairs ending in a distinguished empty list. The notation could be written in dotted form, but ordinary list notation became the more readable abbreviation. The manualized system taught programmers to see a list not as a row of characters but as a linked structure in memory.
That distinction between printed form and structure is easy to miss. A reader sees parentheses and symbols. The machine sees cells whose halves point to other cells or atoms. Dotted notation made the underlying pair structure explicit, while list notation hid the repeated pairing pattern for readability. The two views were not competing truths. They were two ways of looking at the same object: one useful for explanation, one useful for day-to-day programming.
That structure gave LISP its elementary operations. cons built a pair from two expressions. car selected the address part, the first side of the pair. cdr selected the decrement part, the rest of the pair. atom tested whether an expression was an atom. eq compared atoms. These were small operations, but they were not merely conveniences. They were the machine-facing vocabulary from which symbolic programs could be built.
A list like (A B C) was not just a printed sequence. It abbreviated a structure whose first cell pointed to A and to the rest of the list; the next cell pointed to B and to the rest; the next to C and to the empty list. That mattered because a program could take the list apart recursively. It could ask for the first element, recur on the rest, construct a new list, compare symbols, or stop at the empty list.
This made lists a good fit for expressions that were naturally nested. A predicate-calculus formula, a function application, or a rule with subclauses did not have to be flattened into a rigid record. It could be represented as a tree of lists. The same primitive operations could operate at the top level or descend into subexpressions. That gave LISP a uniformity that was pedagogically clean and practically valuable.
For AI, this was a powerful shift. Logical formulas, plans, theorem fragments, property records, and program forms could all be represented as nested symbolic structures. The shape of the data no longer had to be hidden inside ad hoc arrays or procedural conventions. The shape could be the thing the program inspected.
The same structure also kept LISP from being pure abstraction. Its lists were mathematical enough to support recursive definitions, but concrete enough to live in fixed-size machine words. If one looks only at the definitions, LISP seems like a clean theory of symbolic functions. If one looks only at the cells, registers, and free-storage lists, it seems like a memory management technique for symbolic programs. Historically, it was both at once.
That duality explains why LISP became more than a notation. Symbolic AI needed to create temporary expressions constantly: candidate proofs, transformed formulas, partial plans, lists of differences, lists of properties, and newly constructed program fragments. cons, car, and cdr made those structures cheap to express. They also made their machine cost visible. Every symbolic expression had to occupy cells; every cell had to be allocated; every allocation had to be reclaimed or the machine would fill with abandoned structure.
The language therefore began with an elegant idea that immediately became an infrastructure problem. Lists gave symbolic reasoning a common medium. They also forced the system to decide how that medium would be stored, traversed, copied, erased, and eventually forgotten.
The result was not a modern tutorial language divorced from its implementation. Early LISP showed its machinery. A programmer learning car and cdr was learning both recursive decomposition and a trace of how the IBM 704 represented a pair. A programmer learning cons was learning both an abstract constructor and the operation that consumed a real cell from available storage. The theory was clean because the representation was small; the representation was useful because the theory gave it disciplined operations.
This is why the language could teach a habit of thought. To process a symbolic object was to ask whether it was atomic, split it into parts, recurse over those parts, and rebuild a result. The elementary functions were not isolated tricks. Together they made a style of symbolic decomposition feel natural.
M-Expressions versus S-Expressions
Section titled “M-Expressions versus S-Expressions”McCarthy’s original notation plan did not simply say, “Program directly in S-expressions.” The 1958 memo distinguished S-expressions from M-expressions. S-expressions were the symbolic structures, the data representation made from atoms and pairs. M-expressions were intended as the more conventional external language for writing functions over those structures.
That distinction made sense in 1958. Many programmers expected a language to look algebraic. FORTRAN’s success had trained people to read formulas in an infix, mathematical style. McCarthy’s plan preserved that expectation: write functions in a higher-level mathematical notation, then have them operate on S-expressions underneath. The result would be a symbolic language with an external notation that looked less alien than nested parentheses.
But LISP’s later history did not follow that plan cleanly. McCarthy later described S-expressions becoming the universal LISP language, while M-expressions remained mostly planned or partial notation. The strongest available source for that adoption story is McCarthy’s retrospective sections rather than a paginated contemporary one, so the broad shape — the internal form became the practical form — should be read as historical irony rather than a precisely dated transition.
That reversal should not be overstated into inevitability. In 1958, a cleaner external notation was a reasonable goal. It promised to make symbolic functions look like the algebraic expressions programmers already knew how to read. M-expressions belonged to that ambition. They were part of McCarthy’s effort to present the language as a serious mathematical notation rather than as a pile of memory cells.
The reason was not that parentheses possessed mystical power. It was that S-expressions were what the evaluator consumed. Once a system can read a symbolic expression as data and then evaluate it as a program form, the distinction between “the notation for programs” and “the notation for data” becomes unstable. A programmer can type the structure the machine already understands. A program can construct another structure in the same form. The printed representation, the internal representation, and the executable representation begin to line up.
That alignment is the heart of the chapter. In many languages, programs describe operations on data from a distance. In LISP, the program itself could be represented as a list. A conditional expression, a function application, a quoted symbol, or a function definition could be placed inside the same nested structure as the data it manipulated. The language did not erase all boundaries between code and data, but it made the boundary permeable enough for symbolic AI to exploit.
The M-expression/S-expression reversal is also a useful warning about design history. Designers do not always know which part of a system users will adopt. McCarthy’s mathematical ambitions mattered. The intended external language mattered. But the working substrate mattered more. Once implementers and users had a form that could be read, evaluated, printed, copied, and transformed, that form had practical gravity.
The practical gravity came from feedback. If the system printed an S-expression, the programmer could read it. If the programmer typed an S-expression, the system could read it. If a program constructed an S-expression, the evaluator could treat it as a form. Each step reduced the distance between internal representation and external work. M-expressions promised a friendlier front door; S-expressions became the room in which the work was actually done.
This is where Steve Russell’s presence belongs, though without turning the story into folklore. Russell came out of a hands-on MIT programming culture, later famous for work on Spacewar! on the PDP-1. The strongest available source is not biography but the LISP 1.5 manual, which credits Russell and Daniel Edwards with programming the interpreter. That credit is enough to keep the implementation collective. McCarthy supplied the formal language design; Russell, Edwards, Hart, Levin, Minsky, and others helped turn the design into an environment programmers could use.
That collective shape matters because a theory can be attributed through papers and formal definitions, while a tool accumulates through use, implementation, compiler work, manual writing, and decisions made under machine constraints. LISP’s notation story sits exactly at that crossing point. The formal design distinguished M-expressions from S-expressions; the tool culture found that the machine’s own symbolic form was good enough, and often better, for the work at hand.
It was contingent, not fated.
eval, Lambda, cond, and Recursion
Section titled “eval, Lambda, cond, and Recursion”The most compact way to see LISP’s theory side is to follow eval.
McCarthy’s 1958 memo and 1960 CACM paper built the language around recursive functions of symbolic expressions. Lambda notation gave a way to define functions. cond gave a way to branch on tests. Elementary operations such as atom, eq, car, cdr, and cons gave a base vocabulary. Recursive definitions then made it possible to state a procedure by cases: if the expression is empty, stop; if it is an atom, treat it one way; otherwise take the first part, process the rest, and combine the results.
This was a different way of writing programs from the numerical style that had made FORTRAN successful. The program’s main objects were not arrays of numbers but expressions whose form mattered. A recursive function could mirror the structure it consumed. If the expression had a head and a tail, the function could have a head case and a tail recursion. If the expression was atomic, the function could stop or look up a property. The program’s control structure followed the data’s shape.
That sounds like mathematics, and in McCarthy’s presentation it was. But eval made the mathematics operational. The evaluator takes an expression and an environment of meanings, then determines what the expression denotes or computes. A quoted expression returns itself. A variable refers to an associated value. A function application evaluates according to the function and its arguments. A conditional evaluates tests until one branch applies. The exact LISP 1.5 machinery is more detailed than that summary, but the historical point is simple: the language contained a description of how symbolic forms become actions.
McCarthy’s later retrospective includes the famous claim that Russell realized the eval definition could be implemented and hand-compiled it for the IBM 704. That anecdote rests on McCarthy’s reminiscence rather than a paginated contemporary source, so the narrower and better-anchored claim is still the load-bearing one: the LISP 1.5 manual credits Russell and Edwards with programming the interpreter, while McCarthy’s formal definitions supplied the theory that made an evaluator meaningful.
That combination changed the feel of programming for symbolic AI. In an IPL-style system, lists and routines could certainly represent symbolic operations. In LISP, a program form itself could be a symbolic expression subject to the same structural operations as other expressions. A program could build an expression, pass it to the evaluator, inspect the result, and construct another expression. That made program-as-data a working technique rather than just a philosophical slogan.
quote was essential to that technique. Without quotation, an expression would normally be evaluated. With quotation, a symbolic form could be protected and treated as data. That made it possible to talk about expressions inside the language without immediately executing them. The distinction between an expression as something to run and an expression as something to inspect became a programmable distinction.
cond deserves special attention because it made recursive symbolic definitions readable. A function over expressions often needs a sequence of cases: if the input is an atom, do one thing; if its first element has a certain property, do another; otherwise recur on a substructure. cond gave those cases a direct expression. It let the mathematical definition and the program shape resemble each other.
Lambda notation similarly linked the language to mathematical logic without making the system purely mathematical. Functions could be described abstractly, but they had to be represented, stored, applied, and evaluated by a real interpreter. The LISP 1.5 manual’s treatment of functions and special forms shows the language becoming a user-facing system rather than a paper calculus.
Special forms are another reminder that the evaluator was not a generic arithmetic engine. Some forms had to control evaluation itself. A conditional should not evaluate every branch before choosing one. A quotation should not evaluate the expression it protects. Function definition and application required rules about arguments, bindings, and names. These rules were the language’s theory expressed as runtime behavior.
The evaluator made that explicit.
One later fault line begins here too. LISP 1.5’s evaluator made design choices about how function names and variable values were treated. Later Lisp-family languages would diverge over namespace design, with debates often summarized as Lisp-1 versus Lisp-2. That later language-family story belongs elsewhere, but its root is visible in this early evaluator machinery: once code is data, the rules for looking up names become part of the language’s deepest infrastructure.
The important point is not that LISP was magic. It is that eval connected the two halves of the system. The theory of recursive symbolic functions became a machine process. The machine process operated over the same list structures that programmers could inspect and construct. That bridge is why the language could serve as both an object of formal analysis and a workbench for AI programs.
IBM 704 Memory and Garbage Collection
Section titled “IBM 704 Memory and Garbage Collection”List processing creates debris.
Every time a symbolic program constructs an expression, it consumes cells. A theorem prover builds candidate expressions. A planning program builds partial structures. A symbolic simplifier constructs replacements. Many of those objects are temporary. They matter for a few steps and then become unreachable. If the programmer must account for every abandoned cell by hand, the elegance of recursive symbolic programming collapses into bookkeeping.
McCarthy’s 1958 memo already treated available space as part of the language problem. The LISP 1.5 manual later made storage allocation and garbage collection explicit system machinery. There was a free-storage list from which fresh cells could be taken. When the available supply ran low, the system could identify cells still reachable from active structures and reclaim the rest.
The defensible claim is specific: LISP made automated mark-and-sweep garbage collection part of the language environment for list cells. The broader priority claim — that LISP invented automatic memory management — does not survive scrutiny. Other list-management and reclamation techniques were already in the air, including reference-counting work associated with FLPL and earlier explicit list management in IPL. LISP’s contribution here is not metaphysical priority. It is integration.
Mark-and-sweep matched the way list structure worked. The system could begin from known roots: active variables, stacks, and structures still reachable by the running program. It could mark every cell reachable from those roots by following car and cdr links. Unmarked cells were no longer reachable by the program and could be swept back into available storage. The exact implementation details belong to the manual, but the conceptual fit is plain: the same links that made recursive symbolic structure possible also made reachability traceable.
That integration mattered historically. A symbolic AI program could be written as if list cells were a renewable medium. The programmer still had to understand structure, sharing, and mutation, but the system took responsibility for finding unreachable cells and returning them to free storage. In a language whose basic act was cons, that responsibility was not optional.
Garbage collection makes the same dual character concrete. A mathematical account of recursive symbolic functions can ignore the question of where abandoned intermediate expressions go. A working AI system cannot. The moment the elegant notation runs on the IBM 704, the machine has to forget. It has to distinguish live structure from dead structure and make memory reusable.
The free-storage list gave that forgetting an operational form. Cells not currently in use were not an abstract pool; they were organized so that cons could obtain them. Reclamation returned dead cells to that same supply. The programmer could still write in terms of symbolic structure, but the runtime kept a material economy underneath: cells borrowed, linked, traversed, marked, swept, and reused.
This is why memory management belongs in the main narrative rather than a footnote. LISP’s list structures made symbolic programs pleasant to express; automatic reclamation helped make them tolerable to run. Without that runtime discipline, the theory would have remained much farther from a usable laboratory instrument.
It also explains why LISP’s memory story is different from a normal implementation detail. The language encouraged programs to create structure freely. It made construction cheap in notation, so the system had to make reclamation systematic in operation. Garbage collection was the hidden partner of cons: one operation made new symbolic structure; the other made sure the old structure did not permanently consume the machine.
The automation also changed the programmer’s burden. A symbolic program still had to be correct about meaning, sharing, and mutation, but it did not have to carry a manual ledger for every temporary list it created. That shift is small only if one ignores how much symbolic AI depended on temporary structure.
LISP 1.5 as a Research Workbench
Section titled “LISP 1.5 as a Research Workbench”By 1962, the LISP 1.5 Programmer’s Manual had turned a cluster of ideas and implementations into a teachable system. The manual’s own credits matter. McCarthy wrote much of it; Paul Abrahams, Daniel Edwards, Timothy Hart, and Michael Levin appear as authors; Levin prepared it for publication; Russell and Edwards are credited with the interpreter; Hart, Minsky, and Levin with compiler work. This was not a single-author artifact. It was an MIT system consolidated by a team.
The manual also shows why LISP became a workbench rather than only a theory. A programmer could sit at the console and work through a READ / EVAL / PRINT cycle: read a symbolic expression, evaluate it, print the result, revise the expression or definition, and continue. That rhythm made symbolic AI experimental. Representations could be tested directly. Functions over lists could be tried on small structures before being embedded in larger programs. The printed form of an expression remained close to the structure being manipulated.
The workbench included more than pure recursive functions. This point blocks another modern projection. LISP 1.5 was not simply a pure functional language wearing old clothes. It included prog, assignment through setq, and mutation-oriented property-list mechanisms. Atoms could carry associated information. Programs could use property lists to attach meanings, flags, functions, or other data to symbols. That was exactly the kind of flexibility symbolic AI wanted, but it means the early system mixed mathematical elegance with practical stateful tools.
Property lists are a good example of the workbench’s feel. A symbol did not have to be just a printed name. It could become a small hub of associated information. In an AI program, that kind of association was useful: a symbol might carry a value, a function, a marker, or domain-specific metadata. This was not the austere picture of a purely mathematical calculus. It was a laboratory convenience built into the language’s symbolic world.
Macros and FEXPRs extended that pattern. The LISP 1.5 manual described mechanisms by which language behavior could be altered or extended. The full later macro culture belongs to later Lisp-family history, but the early infrastructure is already visible: because program forms were symbolic expressions, the language could provide tools for transforming or controlling those forms before ordinary evaluation.
Compiler work belongs in the same layer. An interpreter made eval vivid and made experimentation natural. Compiler contributions by Hart, Minsky, and Levin pointed toward a different need: making LISP fast enough and structured enough for larger research programs. Broader claims about LISP’s spread should be treated with caution, but the local point is well anchored. LISP 1.5 was no longer only a memo or a paper definition. It was a programming system with documentation, implementation credits, console behavior, storage management, and extension mechanisms.
The manualization itself was infrastructure. A system that exists only in local memory and local habits cannot travel far. A manual gives names, examples, conventions, and operating procedures to people who were not present for every design decision. It also freezes, at least temporarily, a moving implementation into a teachable object. LISP 1.5 became something one could learn from a book, not only from an MIT machine room.
That teachability made the workbench reproducible. A reader could learn what counted as an atom, how functions were applied, how the console cycle behaved, where storage management entered, and how extension mechanisms fit the evaluator. The manual did not merely document LISP. It stabilized a research practice.
This is the workbench side of the chapter. AI researchers were not merely admiring recursive functions. They were building structures, attaching properties to symbols, evaluating expressions, debugging representations, and extending the language to fit new symbolic tasks. LISP’s theory gave those activities a compact form. Its machinery made them repeatable.
Handoff Close
Section titled “Handoff Close”LISP’s importance is easiest to misstate when treated as a trophy. It did not originate list processing or AI programming, and AIM-001 was not the finished system. Its importance was that several layers came together in one place: S-expressions, machine-level list cells, recursive functions, cond, lambda notation, eval, automatic mark-and-sweep reclamation, console interaction, property lists, macros, and compiler work.
The honest chronology is more interesting than the trophy version. FLPL marks the FORTRAN detour. AIM-001 lays out the symbolic-expression language and its machine representation. The 1960 paper gives the recursive-functions presentation. The LISP 1.5 manual records the system as a usable environment with a team behind it. Each layer changes the meaning of the one before it.
That bundle made symbolic AI portable in a new way. A researcher could describe symbolic reasoning in the same medium the program manipulated. The language’s theory and its tool environment reinforced each other. LISP was mathematical enough to make symbolic functions legible and mechanical enough to make them runnable.
LISP was not only a beautiful theory that happened to get implemented. It was not only a handy tool that later acquired theoretical prestige. Its power came from the overlap. The recursive theory made the tool coherent; the tool made the theory usable in everyday symbolic programming.
That overlap also made the next institutional step possible.
The language was ready for a more interactive computing culture.
That shift changes the setting.
The next phase of the story moves from language substrate to institutional substrate. Project MAC and time-sharing would change how programmers encountered machines, making interaction less like submitting isolated jobs and more like living inside a computational environment. That later chapter belongs to the AI-lab and time-sharing world. LISP provided one of the languages ready to inhabit it.
Sources
Section titled “Sources”Primary
Section titled “Primary”- John McCarthy. “An Algebraic Language for the Manipulation of Symbolic Expressions.” MIT Artificial Intelligence Project Memo No. 1, September 1958.
- John McCarthy. “Recursive Functions of Symbolic Expressions and Their Computation by Machine, Part I.” Communications of the ACM 3(4), April 1960.
- John McCarthy, Paul W. Abrahams, Daniel J. Edwards, Timothy P. Hart, Michael I. Levin. LISP 1.5 Programmer’s Manual. MIT Press, 1962.
- John McCarthy. “History of Lisp.” HOPL I / ACM SIGPLAN History of Programming Languages, 1978/1979.
- John McCarthy. “Programs with Common Sense.” Symposium on the Mechanisation of Thought Processes, 1959.
- Chapter 12 research contract sources on IPL, Logic Theorist, and GPS, especially
P-868,P-1584, and IPL worklist anchors. - John McCarthy. “The LISP Programming System.” MIT AI Memo No. 8, March 1959.
- MIT AI Memo No. 40. LISP I Programmer’s Manual, 1962.
- John McCarthy. MIT AI Memo No. 99, 1966.
- Daniel G. Bobrow. Early BBN-Lisp papers, 1966-1969.
- Henry G. Baker. “List Processing in Real Time on a Serial Computer.” Communications of the ACM 21(4), April 1978.
Secondary
Section titled “Secondary”- Guy L. Steele Jr. and Richard P. Gabriel. “The Evolution of Lisp.” HOPL II, 1996.
- Herbert Stoyan / Software Preservation Group Lisp History pages.
- Pamela McCorduck. Machines Who Think. 1979 / 2004.
- Daniel Crevier. AI: The Tumultuous History of the Search for Artificial Intelligence. 1993.
- Paul Graham. Lisp essays.
- Computer History Museum Lisp materials.