Structure and Interpretation of Computer Programs - JavaScript Edition
A syllabus-first track for SICP in JavaScript: programming as abstraction, data as interface, state as a controlled danger, interpreters as executable language design, and machines/compilers as the bridge from high-level meaning to low-level execution. The split below covers every major book section as a lesson.
Book source
This syllabus is built from the outline of
Structure and Interpretation of Computer Programs, 2e (JavaScript Edition) by Harold Abelson, Gerald Jay Sussman, Julie Sussman, and Martin Henz. It follows the book's conceptual sequence and section coverage, but the lesson framing, summaries, exercises, and explanations here are original.
recommended split
Use 22 lessons: one lesson for each major section, from 1.1 through 5.5. This covers all five chapters while keeping the catalog readable.
why not 5 chapters?
Five chapter pages are too broad. Each chapter changes the kind of abstraction being taught, and the major sections are where the actual learning units live.
why not every subsection?
Every nested subsection would create roughly eighty tiny pages. Better: each lesson card below names the important subsections and turns them into one coherent assignment.
How to read it
Read linearly if you want the full SICP arc. For the shortest spine, read lessons 01, 03, 04, 08, 10, 13, 14, 19, and 22. That path still hits the core moves: substitution, higher-order functions, data abstraction, generic operations, environments, streams, evaluators, machine models, and compilation.
Lessons are live
All 22 anchors below are now full lesson pages. Each follows one shape — the idea, the JavaScript mechanism, a worked trace or interpreter/data exercise, and the design pressure that forces the next lesson. The track is a single linear spine: every lesson states the exact limitation of the previous model that makes the next one necessary.
Part I - Building Abstractions with Functions
Function abstraction first: names, substitution, process shape, growth, and higher-order construction.
01
Book coverage: 1.1 - expressions, names, environments, function application, conditionals, Newton iteration, black-box functions.
Start with the smallest pieces of a language: expression, value, name, environment, function, predicate, and conditional choice. Newton's square-root method becomes the first real example of a process hidden behind a clean function boundary.
Outcome: explain the substitution model for simple function calls and use local names to make helper functions invisible outside the abstraction.
02
Book coverage: 1.2 - linear recursion, linear iteration, tree recursion, orders of growth, exponentiation, gcd, primality.
Separate the function's mathematical definition from the process it generates. Factorial, Fibonacci, exponentiation, Euclid's algorithm, and primality testing show the difference between recursive shape, iterative state, tree explosion, and asymptotic cost.
Outcome: look at a recursive definition and predict stack growth, time growth, and whether an accumulator can turn it into an iterative process.
03
Book coverage: 1.3 - functions as arguments, lambda expressions, general methods, returned functions.
Turn repeated control patterns into functions that accept functions. Summation, product, accumulation, fixed points, average damping, and returned functions show why JavaScript functions-as-values are not syntax sugar but an abstraction mechanism.
Outcome: write a higher-order combinator, pass behavior into it, and return specialized behavior from it.
Part II - Building Abstractions with Data
Data abstraction, closure, symbolic data, multiple representations, and generic operations.
04
Book coverage: 2.1 - rational numbers, abstraction barriers, what data means, interval arithmetic.
Data becomes a contract between constructors and selectors. Rational numbers and intervals teach the core barrier: clients should depend on what operations mean, not how pairs, numbers, or objects happen to represent them.
Outcome: design a representation that can change without forcing client code to change.
05
Book coverage: 2.2 - sequences, trees, sequence interfaces, and the picture language.
Pairs close over pairs, so data can become a tree. Lists, maps, filters, accumulators, nested structures, and the picture language show the same interface pattern over many shapes of data.
Outcome: use sequence operations as a conventional interface that hides traversal details.
06
Book coverage: 2.3 - strings, symbolic differentiation, sets, and Huffman encoding trees.
Programs can manipulate symbols as data. Differentiation turns algebra into tree rewriting, sets expose representation trade-offs, and Huffman trees make the cost model visible in the shape of the encoding tree.
Outcome: represent a symbolic language as data and write recursive transformations over that representation.
07
Book coverage: 2.4 - complex numbers, tagged data, data-directed programming, and additivity.
One abstract object can have many useful representations. Complex numbers in rectangular and polar form motivate tags, operation tables, and the additive style where a new representation can be installed without rewriting old code.
Outcome: explain data-directed dispatch and when it beats a tower of conditionals.
08
Book coverage: 2.5 - generic arithmetic, combining different types, and symbolic algebra.
Generic operations extend data-directed programming into a system. Coercion, type towers, and symbolic algebra show the central tension: add new types, add new operations, and keep the representation barriers intact.
Outcome: design a small generic arithmetic table and reason about where coercion should live.
Part III - Modularity, Objects, and State
Assignment introduces identity, time, mutation, concurrency hazards, and delayed computation.
09
Book coverage: 3.1 - local state variables, the benefits of assignment, and its costs.
Assignment gives objects identity across time. Bank accounts and monitored functions show what state buys, then immediately show the price: substitution is no longer enough because evaluation now depends on history.
Outcome: state when mutation is an abstraction tool and when it destroys local reasoning.
10
Book coverage: 3.2 - evaluation rules, function application, frames, local state, and internal declarations.
The substitution model gives way to environments: frames, bindings, enclosing scopes, and function objects with remembered environments. This is the operational model that makes closures and local state precise.
Outcome: draw an environment diagram for a closure that captures local state.
11
Book coverage: 3.3 - mutable list structure, queues, tables, digital circuits, and constraints.
Mutation moves from variables into data structure. Queues, tables, event-driven circuit simulation, and constraint propagation show how local mutation can power systems that model changing worlds.
Outcome: build a mutable data abstraction while keeping mutation behind a small interface.
12
Book coverage: 3.4 - time in concurrent systems and mechanisms for controlling concurrency.
Once multiple processes interleave, mutation becomes a coordination problem. Serializers, races, ordering, deadlock pressure, and protected operations expose why shared state and time are inseparable.
Outcome: diagnose a race by naming the shared state and the missing serialization boundary.
13
Book coverage: 3.5 - delayed lists, infinite streams, stream programs, delayed evaluation, and modularity.
Streams recover modularity by separating what a sequence is from when its elements are computed. Infinite data, signal processing, numerical methods, and stream-based state all become ordinary sequence programs.
Outcome: explain delay/force and write a stream pipeline that can describe an infinite computation.
Part IV - Metalinguistic Abstraction
Interpreters turn language design into data and functions.
14
Book coverage: 4.1.1-4.1.4 - evaluator core, represented components, evaluator data structures, and running the evaluator.
Build an evaluator for a JavaScript-like language in JavaScript. Evaluation, application, environments, primitive functions, compound functions, and the driver loop make the language's semantics executable.
Outcome: trace how an evaluator dispatches on syntax and uses environments to give names meaning.
15
Book coverage: 4.1.5-4.1.7 - data as programs, internal declarations, and separating syntactic analysis from execution.
After the evaluator works, split syntax analysis from execution so repeated evaluation does less work. This is the first step from interpreter-as-specification toward implementation strategy.
Outcome: describe why analyzing once and executing many times changes the evaluator's cost model.
16
Book coverage: 4.2 - normal order, applicative order, a lazy evaluator, and streams as lazy lists.
Change the evaluator and the language changes. Thunks, memoization, forcing, and delayed arguments make laziness a semantic choice rather than a library trick.
Outcome: compare applicative-order and normal-order evaluation on the same expression.
17
Book coverage: 4.3 - search, amb-style choice, example programs, and the nondeterministic evaluator.
Make search part of the language. Choice points, backtracking, failure continuations, and constraint-style programs show how a new evaluator can expose a new programming model.
Outcome: model a search problem as choices plus constraints instead of nested loops.
18
Book coverage: 4.4 - deductive retrieval, query evaluation, logic programming limits, pattern matching, unification, streams, frames, and bindings.
A query system turns facts and rules into a tiny logic language. Pattern matching, unification, stream-based search, rule application, and frames make declarative retrieval concrete.
Outcome: explain how a query engine searches assertions and rules to satisfy a pattern.
Part V - Computing with Register Machines
The final arc lowers evaluators into machines, storage, explicit control, and compiled code.
19
Book coverage: 5.1 - machine language, abstraction in machine design, subroutines, stacks, and instruction summaries.
Replace high-level functions with registers, operations, tests, branches, labels, and a stack. The lesson is not nostalgia for assembly; it is the cost model behind recursion and control.
Outcome: translate a simple recursive computation into registers plus explicit stack operations.
20
Book coverage: 5.2 - machine model, assembler, execution functions, and performance monitoring.
Build the machine as a program. The simulator, assembler, instruction execution functions, tracing, and performance counters make the hardware model inspectable.
Outcome: explain how an assembler turns controller text into executable instruction objects.
21
Book coverage: 5.3 and 5.4 - memory as vectors, garbage collection, dispatcher, applications, blocks, assignments, declarations, and running the evaluator.
Memory stops looking infinite. Vectors, free lists, garbage collection, and the explicit-control evaluator show how environments, continuations, and function application become concrete machine state.
Outcome: connect evaluator concepts from Part IV to registers, stack discipline, and heap allocation.
22
Book coverage: 5.5 - compiler structure, compiling components, applications, returns, instruction sequences, examples, lexical addressing, and evaluator interop.
The capstone: compile high-level expressions into register-machine instructions. Instruction sequences, linkage, preserving registers, lexical addressing, and compiled/evaluated interop close the loop from language design to execution.
Outcome: state what a compiler preserves from the evaluator and what it precomputes to run faster.
Position in the library
This is the Foundations bridge between general programming craft and language/runtime systems. It complements the functional-programming series: FP teaches the programming discipline; SICP teaches the deeper abstraction stack underneath programming languages, interpreters, and machines.