Structure and Interpretation of Computer Programs
Abelson and Sussman's MIT textbook, which treats programming as a medium for expressing ideas about process rather than as a set of techniques for instructing a machine — and which is as much a book about abstraction as about code.
- First published
- 1984
- Publisher
- MIT Press
- Pages
- 542
- Shelf
- Technology
- Level
- Deep
- ISBN-13
- 9787111135104
Record checked against
Two sources agreed on 1984; a third reported differently (openlibrary 1985, wikidata 1996, wikipedia 1984).
Catalogue note
- Reads as
- TechnicalAssumes and builds craft knowledge.
- Level
- Advanced / AdvancedAssumes you have read around the subject already.
- Approach
- Applied
- Written for
- Engineers, Specialists and serious readers
- Ideas
Saved in this browser only — no account, nothing sent anywhere. My library
Read this if
- You build software and want the ideas under the tools.
- You work in this area and want depth rather than an overview.
- You have read around this already and want a book that assumes it.
The central claim
Their famous formulation is that programs must be written for people to read, and only incidentally for machines to execute.
The book follows from that: it is about controlling complexity through abstraction, and the language it uses — a Scheme dialect — is chosen because it has almost no syntax, which keeps attention on the ideas rather than on the notation.
Programs are written for people to read and only incidentally for machines to execute. Everything follows from that.
Devmark’s reading — not a quotation from the book
Procedural abstraction
The opening section builds the idea that a procedure is an abstraction — a name for a process whose implementation the caller need not know — and develops recursion, iteration, and the analysis of how processes consume time and space.
Their distinction between a recursive procedure and a recursive process is the kind of precision the book is made of, and it is the sort of thing most programming education never establishes.
Data abstraction
Their second section builds data structures from procedures, establishing that the distinction between code and data is a convenience rather than a fundamental one.
The construction of pairs entirely out of functions is the demonstration that sticks: it shows that data can be a behaviour rather than a storage layout, which is a genuinely disorienting idea the first time.
Higher-order procedures
Procedures that take and return procedures, which the book treats as ordinary rather than advanced.
This was radical in mainstream programming education when published and is now standard in most languages — a case where the book was describing the future, and where readers coming to it now will find the ideas familiar from languages that adopted them later.
State, time and assignment
The third section introduces mutable state and argues carefully about what it costs: once a procedure has state, it is no longer a mathematical function, reasoning about it becomes harder, and concurrency becomes possible to get wrong.
Their treatment of the substitution model breaking down when assignment appears is one of the clearest explanations available of why functional code is easier to reason about.
Once assignment appears, you can no longer reason by substitution. That is the price, stated precisely.
Devmark’s reading — not a quotation from the book
Metalinguistic abstraction
The fourth section builds an interpreter for Scheme in Scheme, and then variations — a lazy evaluator, a non-deterministic one, a logic programming language.
This is the book's summit. The realisation that a language is a program, and that designing a language is a normal thing to do when the problem calls for it, is what people mean when they say the book changed how they think.
The register machine
The final section descends to a register machine and a compiler, connecting the high-level material to the physical execution that Petzold's book builds up to from the other direction.
Reading *Code* and this book together covers the whole stack from transistor to interpreter, which very few pairs of books manage.
Why it is difficult
It is genuinely hard, and the difficulty is intended. The exercises are substantial, several are open-ended, and the book does not work as a read-without-doing text.
Its reputation for defeating readers is earned. A person who reads it without completing exercises will retain the vocabulary and none of the capability.
Its status now
MIT replaced it in the introductory curriculum, on the reasoning that modern engineering involves composing large unfamiliar systems rather than building from primitives — a defensible argument about what a first course should do.
The book's value did not change; its role did. It is now read by people who choose to rather than by people assigned to, which is arguably the better readership for it.
What to take from it
The disposition, more than any technique: that complexity is controlled by building layers of abstraction, and that when the available abstractions do not fit, building a language is a legitimate move.
Work the exercises or do not bother. It is a book that only transfers through effort, and it is freely available online, so the only cost is the time it genuinely demands.
What to take away
- 01Abstraction is the tool for complexityThe whole book is about building layers so that each one can be reasoned about without the one below.
- 02Code and data are not fundamentally differentBuilding pairs entirely out of functions demonstrates that data can be behaviour.
- 03Assignment costs you substitutionOnce state appears you can no longer reason about a procedure as a mathematical function.
- 04Designing a language is a normal moveWhen the available abstractions do not fit the problem, building one that does is legitimate.
- 05It only transfers through exercisesReading it without doing the work leaves the vocabulary and none of the capability.
