01 — define & lambda
Everything is a definition or an expression; functions are values named by define.
(define (double x) (* 2 x))
(define halve (lambda (x) (/ x 2)))§ 02 — Eras · 1975
LISP reduced to a kernel small enough to verify
Left: era context, features, and the 101 hello. Right: 3 core concepts, 3 deeper 201 lessons, the factorial specimen, and where Scheme lives today — each column scrolls on its own.
LISP had sprawled into dialects with unclear semantics. Scheme reduced it to a kernel small enough to reason about completely.
Minimalism pushes every decision to the library — and the tower of Schemes fragmented the idea all over again.
Session one is the smallest program that still counts as speaking Scheme: what every tutorial prints first, in the dialect that mattered when the language arrived (1975).
(display "Hello, world")
(newline)101First contact — hello world and 3 ideas that define how Scheme reads. 201 — 3 lessons on mechanisms you meet after the factorial specimen: the sharp edges practitioners actually use.
3 fragments, each naming a habit of mind in Scheme. Read the note, then the code — together they are the 101 in one sitting.
01 — define & lambda
Everything is a definition or an expression; functions are values named by define.
(define (double x) (* 2 x))
(define halve (lambda (x) (/ x 2)))02 — the continuation
call/cc hands you the rest of the computation as a callable value — time travel, typed.
(call/cc
(lambda (k) (k 42))) ;=> 4203 — tail calls
Proper tail calls are guaranteed: recursion that compiles to a jump, forever.
(define (loop n)
(if (= n 0) 'done (loop (- n 1))))The 201 assumes you have read the 101 and the specimen. Each lesson is one mechanism — what it is for, how it looks in code, and the trap or payoff that makes Scheme distinctive at scale.
syntax-rules macros rename their bindings so they cannot capture the caller’s variables — the discipline that makes Lisp macros composable.
(define-syntax my-or
(syntax-rules ()
[(_ a b) (let ([t a]) (if t t b))]))A continuation can be captured and resumed later, turning loops into generators and letting a program abandon its current stack entirely.
(define (generate lst)
(call/cc
(lambda (return)
(for-each (lambda (x) (call/cc (lambda (k) (set! return k) (k x)))) lst)
(return #f)))))Records copy on write: changing one field yields a new record, leaving the original untouched — the pattern behind modern immutable state.
(define r (make-record "name" 30))
(define r2 (record-update r "name" "Perch"))
;; r still says "name"The continuation: call/cc hands you the rest of the computation as a value you can call later. LISP reduced to a kernel small enough to verify.
(call/cc
(lambda (k) (k 42)))
;=> 42 — the future itself, as a valueinstallbrew install mit-scheme
runmit-scheme --script fact.scm
Racket (education, research), Guile (GNU scripting), and JavaScript’s closures trace their semantics here.