sicp.io
Chapter 2 · Checkpoint

Follow the interface. Preserve the invariant. Extend the table.

Use twenty runnable programs to reconnect every Chapter 2 lesson: abstraction barriers, procedural data, sequences, trees, identity, symbolic structure, sets, generic dispatch, coercion and dropping, sparse algebra, painters, frames, and recursive picture composition.

Guiding question

Can you explain a data program while keeping its abstract contract, representation invariant, identity, symbolic structure, registered methods, conversion path, and geometric frame separate?

  • Keep representation knowledge behind constructors and selectors
  • Recognize behavior-preserving procedural data representations
  • Follow a sequence one cdr at a time
  • Follow both branches of a tree without assuming its depth
  • Distinguish one shared object from two equal objects
  • Compose enumeration, filtering, mapping, and accumulation
  • Transform symbolic expression data through simplifying constructors
  • Distinguish quotation, identity, and recursive structural equality
  • Dispatch one generic operation through a data type tag
  • Propagate lower and upper bounds through an interval interface
  • Compare unordered, ordered, and tree-based set representations
  • Use one code-tree representation to encode and decode branch paths
  • Choose rectangular or polar contents behind one complex-number interface
  • Move mixed numeric values through explicit coercion or raising paths
  • Add and multiply sparse polynomials through generic tagged methods
  • Map one unit-square painter through square or skewed frames
  • Compose transformed painters and produce a finite recursive segment set
  • Install a new representation without editing the generic dispatcher
  • Raise values to a common arithmetic method
  • Drop a result only when projection and re-raising preserve its information

The rational, interval, and complex programs keep concrete contents behind constructors and selectors. The procedural-data lesson makes the contract even more explicit: a pair or point can be represented by a closure if the same observable operations remain available.

Sequence and tree procedures follow the shape of their data. Shared identity adds a separate question about allocation, while quotation separates expression-shaped data from an application to evaluate. eq? and equal? then answer different identity and structure questions.

The pipeline and symbolic differentiator divide work into stages whose representations meet at named boundaries. Set programs compare unordered scanning, ordered early exit, and one-branch tree search without confusing the abstract set operations with those traversal choices.

Operation-table examples keep registration separate from application. A package installs methods under operation and type keys; apply-generic remains unchanged when another representation arrives. The arithmetic tower similarly keeps raising and dropping policy outside same-type arithmetic.

Huffman, complex, coercion, and polynomial examples preserve their own structural invariants. The generic arithmetic lesson adds a stricter simplification boundary: a projected result is dropped only after raising it again reproduces the original value.

The picture language applies the same abstraction ideas geometrically. Painters describe unit-square segments, transformations construct subframes and new painters, and only the final application emits SEG lines. The monochrome SVG is derived from that Lispex transcript rather than a duplicate TypeScript drawing model.

SICP code346 of 1,048,576 UTF-8 bytes
Examples
Result
Output
Value
Diagnostic
Execution trace0 / 0 events
    Programs run in the browser with their result and execution trace.
    Expected result

    The original fifteen programs retain their documented lesson results. The procedural-data program returns (left right 1 2 3). Quotation returns ((+ x 3) + x (+ 10 3) #t #t #f). Set representations return ((1 3 5) (4 1 3 5) #f (1 3 4 5 7)). Data-directed installation returns (4 8 rectangular swapped 3 4 25 3 4 25). The arithmetic tower returns ((rational 7 2) (integer 1) (integer 5) (complex (rational 3 1) (rational 1 1))). Picture examples also emit SEG transcripts under fixed runtime limits for the visualizer.

    Trace focus

    Locate constructor and selector calls, closure creation and later messages, sequence and tree recursion, allocation identity, quote boundaries, structural comparisons, set early exits, operation-table put/get calls, type-tag dispatch, raise and project paths, polynomial term merging, frame-coordinate mapping, subframe construction, and final SEG emission. The execution traces record the exact selected runs under fixed runtime limits.

    Review

    Twenty checks for reasoning about data systems

    What does an abstraction barrier protect us from changing?

    Answer The pair is useful machinery, while the public idea is the interface. Keeping representation knowledge behind a stable interface makes later changes local instead of contagious.

    How do recursive procedures follow the shape of a list?

    Answer A vector uses an indexed sequence convention. vector-ref selects an item by position, while vector-set! changes one position without rebuilding the whole vector.

    How does one procedure work across every depth of a tree?

    Answer The control structure mirrors the data definition. That correspondence is why the procedure works for a shallow list and a deeply nested tree without separate cases for each depth.

    Why is shared identity different from merely equal contents?

    Answer The printed #0= label introduces the shared object and #0# refers to that same object again. The labels preserve identity that ordinary list notation would hide.

    How does a sequence pipeline turn nested recursion into named stages?

    Answer accumulate combines the transformed sequence with + and the initial value 0. The complete program still recurses, but its control is distributed across reusable stages instead of fused into one special-purpose procedure.

    How do data constructors keep algebraic simplification separate from differentiation rules?

    Answer make-sum and make-product own representation cleanup. They remove additions by zero, multiplications by zero or one, and combine numeric operands, so the differentiation cases state their mathematical rules without repeating simplification details.

    How does an operation table preserve one interface across different representations?

    Answer apply-generic removes the tag only after get has selected the matching procedure. Client code names magnitude and supplies tagged data without asking which representation it contains. Adding a representation changes the table rather than the generic interface.

    How can arithmetic use a range without depending on how its two bounds are stored?

    Answer Addition combines the two lower bounds and the two upper bounds. Multiplication must consider all four endpoint products because the smallest or largest result can come from a different corner when an interval crosses zero. The result is the interval enclosure of those possible products.

    Which work becomes unnecessary when a set representation promises increasing order?

    Answer union-ordered-set compares the two heads. It keeps the smaller one and advances that list; equal heads produce one element and advance both. Every recursive step consumes at least one current head, preserving sorted order without restarting a search from the beginning.

    How can one weighted tree determine both the bits we write and the symbols we recover?

    Answer Encoding asks whether the next symbol belongs to the left or right branch and records 0 or 1 before continuing below that branch. Decoding consumes the same decisions in the opposite direction. Reaching a leaf emits its symbol and returns to the root for the next code word. Equal weights can admit another valid tree; the explicit insertion rule fixes the tree used by these runs.

    How can one complex-number interface preserve the advantages of rectangular and polar representations at the same time?

    Answer The first program constructs 3 + 4i in both forms and asks the same four selectors to observe them. close? records that the inexact trigonometric path agrees within a stated tolerance. The second program adds through real and imaginary parts and deliberately returns a rectangular object, while multiplication combines magnitudes and angles and returns a polar object. Generic selectors verify the abstract results without exposing either object’s contents to the caller.

    How can generic arithmetic choose a common type without hiding failed coercions or looping between peer representations?

    Answer The second program replaces pairwise coercion choices with an ordered tower. rank identifies integer, rational, and complex levels. raise performs only the next upward conversion, and raise-to repeats it until both values reach the higher input rank. Integer plus rational therefore uses rational addition; rational plus complex uses complex addition after one raise; an unrelated polynomial tag has no rank and returns no-common-type. A tower reduces ambiguity for these ordered types, but it does not imply that every data type belongs in one hierarchy or that downward projection is always lossless.

    How can a generic arithmetic system manipulate polynomial structure without scattering term-list details through client code?

    Answer The second program multiplies one term by every term in the other polynomial, shifts orders by addition, multiplies coefficients, and merges the partial products through add-terms. Multiplying x + 1 by x − 1 creates two middle terms that cancel, leaving x² − 1. A separate evaluator uses the package selectors and reports 8 at x = 3. This lesson models sparse univariate integer-coefficient polynomials with tagged addition, multiplication, normalization, and evaluation.

    How can one painter describe the same picture inside square, skewed, or scaled frames?

    Answer The first run places one outline-and-cross painter inside a square frame. The second applies a diamond painter to a skewed frame. The painter definitions do not contain the final page coordinates. Each run prints one SEG line per mapped segment, and the app-local visualizer parses those transcript lines into a monochrome SVG. The returned (segments n) value remains a separate observation.

    How can a few frame transformations create a language of reusable picture combinations?

    Answer The first run places four transformed chevrons in a square. The second defines right-split recursively: the left half keeps the original painter while the right half stacks two smaller copies. At depth three, a three-segment base painter produces 45 mapped segments. The visualizer draws exactly the SEG lines produced by Lispex and caps only the browser rendering, not the runtime’s own execution limits.

    If constructors and selectors satisfy the same contract, must an abstract data value have one particular physical representation?

    Answer The point example uses message dispatch. make-point returns a procedure that answers x, y, and sum messages. The selectors know only those messages. A conventional pair, a vector, or another closure could replace this implementation if the same observable constructor-selector behavior remains available.

    How does the evaluator know when (+ x 3) is an application to run and when it is a list to inspect?

    Answer eq? asks whether its operands denote the same symbol or object identity. equal? descends through compound data and compares structure and leaves. The second program therefore distinguishes one shared list from a separate list with the same contents while still recognizing their structural equality.

    Which operations become cheaper when a set representation promises order or a search-tree shape?

    Answer A binary search tree stores smaller entries on the left and larger entries on the right. Each comparison chooses one branch instead of scanning every entry. tree->list performs an in-order traversal and recovers an ordered sequence. The balanced hand-built tree demonstrates the search rule, while a one-sided tree exposes a linear path.

    How can a generic system gain another representation or operation without reopening one central conditional?

    Answer The second program begins with only an integer description method. A rational value initially produces no-method. Installing one more table entry makes the same describe dispatcher accept it without editing the dispatcher or the integer package. Additivity here is explicit and finite: extension occurs by registering another method under a new key.

    How can mixed arithmetic find a common type and later return to a simpler type without discarding information?

    Answer drop attempts the reverse direction conservatively. A rational projects to an integer only when its denominator is 1. A complex value projects to its real component only when its imaginary component is exactly zero. The projected value is raised again and compared with the original before simplification continues, so a nonzero imaginary component cannot disappear.