Skip to main content

Module 5: Abstraction & Interpretation: Case Studies

These case studies connect SICP-style abstraction to real interpreters, DSLs, evaluators, and mutation costs.


Case Study 1: Tiny Lisp Interpreter As eval / apply​

Scenario: A learner thinks interpreters are magic. A tiny Lisp shows that evaluation is an explicit recursive process over expressions and environments.

Source anchor: Peter Norvig's (How to Write a Lisp Interpreter in Python) provides a compact interpreter walkthrough that makes eval and apply concrete.

Module concepts: eval, apply, environment, expression, procedure.

Wrong Approach​

"The language runtime just knows what code means."

Better Approach​

Model evaluation:

self-evaluating:
numbers, strings

symbol:
lookup in environment

combination:
eval operator
eval operands
apply procedure

Tradeoff Table​

ChoiceGainCost
Treat interpreter as black boxLess conceptual overhead initiallyWeak transfer to real evaluator design
Trace eval/apply explicitlyClear operational modelMore recursion and environment detail
Jump straight to host-language evalQuick demoHides the core abstraction being taught

Failure Mode​

Learners can run examples but cannot explain why symbol lookup, recursion, or procedure application behaves the way it does.

Required Artifact​

Write an eval/apply trace for (+ (* 2 3) 4).

Project / Capstone Connection​

Use this tracing style for any DSL, rules engine, or interpreter-style component you design later.


Case Study 2: Environment Model Explains Closures​

Scenario: A function returns another function that remembers a variable. The substitution model becomes awkward; the environment model explains it.

Source anchor: SICP's environment model and Norvig's lispy environment implementation anchor this case.

Module concepts: closure, lexical scope, environment frame, binding.

Wrong Approach​

"The variable disappeared when the outer function returned."

Better Approach​

Draw frames:

make_counter frame:
count -> 0

returned closure:
code + pointer to environment

Tradeoff Table​

ChoiceGainCost
Force substitution model everywhereOne simple storyBreaks down on closures and mutation
Use environment framesExplains lexical scope directlyRequires graph-like reasoning
Memorize closure behavior by exampleFast recall for simple casesWeak debugging model

Failure Mode​

A learner predicts that captured variables vanish after return and cannot reason about stateful closures or lexical scope bugs.

Required Artifact​

Draw environment frames for a counter closure after three calls.

Project / Capstone Connection​

Apply this model when you design callback-heavy code, templating evaluators, or scoped configuration languages.


Case Study 3: DSL Dispatcher For Build Rules​

Scenario: A build tool has commands like compile, test, package, and deploy. The first implementation is a giant if/else.

Source anchor: Crafting Interpreters builds interpreters through scanning, parsing, representation, and execution, which grounds the move from string conditionals to a DSL model.

Module concepts: DSL, parser, AST, dispatcher, abstraction barrier.

Wrong Approach​

Keep adding stringly typed conditionals.

Better Approach​

Represent commands:

AST:
Task(name, dependencies, action)

Evaluator:
resolve dependencies
execute action
record result

Tradeoff Table​

ChoiceGainCost
Giant if/else dispatcherFast first implementationHard to extend and validate
AST + evaluatorClear abstraction barrierParser and representation work upfront
Full general-purpose scriptingMaximum flexibilityMuch larger surface to secure and debug

Failure Mode​

Adding one new command duplicates parsing, validation, and dependency logic across branches until the tool becomes brittle.

Required Artifact​

Design a tiny build-rule AST and evaluator pseudocode.

Project / Capstone Connection​

Use this pattern when later projects need command dispatch, workflow engines, or structured configuration.


Case Study 4: Mutation Breaks Equational Reasoning​

Scenario: Two calls to a function return different results because hidden state changes inside the function.

Source anchor: SICP's assignment and mutation chapters frame the cost of state and the environment model.

Module concepts: mutation, state, referential transparency, streams.

Wrong Approach​

Assume a procedure call can always be replaced by its value.

Better Approach​

Name the state:

pure function:
same input -> same output

stateful procedure:
depends on hidden environment

repair:
pass state explicitly or isolate mutation

Tradeoff Table​

ChoiceGainCost
Hidden mutable stateConvenient local updatesHarder reasoning and testing
Explicit state passingClear behaviorMore plumbing in APIs
Isolated mutation boundaryBalance of clarity and practicalityRequires discipline at the boundary

Failure Mode​

Refactors or tests assume referential transparency, but hidden state changes make repeated calls diverge unexpectedly.

Required Artifact​

Compare a pure and mutable accumulator with an environment trace.

Project / Capstone Connection​

Use this lens when deciding where later systems or tooling projects should allow mutation versus preserve pure transformations.


Case Study 5: Normal-Order Saves Work, Or Repeats It​

Scenario: A conditional-like function receives an expensive expression. Applicative order evaluates it even when unused; normal order delays it but may duplicate work.

Source anchor: SICP evaluation-order material and interpreter implementation make the distinction concrete.

Module concepts: applicative order, normal order, laziness, thunk, memoization.

Wrong Approach​

"Evaluation order is an implementation detail."

Better Approach​

Trace both:

applicative:
evaluate all arguments first

normal:
substitute/delay until needed

lazy with memoization:
delay once, cache result

Tradeoff Table​

ChoiceGainCost
Applicative orderPredictable eager executionWastes work on unused branches
Normal orderCan avoid unnecessary workMay repeat expensive evaluation
Lazy with memoizationAvoids repeated work after first forceExtra runtime machinery

Failure Mode​

An apparently harmless abstraction either evaluates an error-producing branch too early or recomputes an expensive thunk many times.

Required Artifact​

Write an evaluation trace for an expression where normal order avoids an error or expensive computation.

Project / Capstone Connection​

Use this distinction when later designs introduce deferred configuration, streaming pipelines, or cached computations.


Source Map​

SourceUse it for
Norvig: lis.pytiny Lisp interpreter and environments
Crafting Interpretersscanning/parsing/AST/evaluation path
SICP JS editionevaluation, abstraction, mutation

Completion Standard​

  • At least three artifacts are completed.
  • At least one artifact traces eval/apply.
  • At least one artifact draws environment frames.
  • At least one artifact designs a tiny DSL or interpreter.