← the guideThe Systems Age

§ 02 — Eras · 1975

Scheme

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.

creators
Gerald Sussman & Guy Steele, MIT, 1975
status
alive · Racket, Guile, teaching (SICP)
lineage
← LISP→ Common Lisp⇢ JavaScript

The problem it solves

LISP had sprawled into dialects with unclear semantics. Scheme reduced it to a kernel small enough to reason about completely.

The problem it carries

Minimalism pushes every decision to the library — and the tower of Schemes fragmented the idea all over again.

Key features

a minimal kernel
A handful of special forms; everything else is a library built on top of them.
proper tail calls
Recursion in tail position is a jump, not a stack frame — infinite loops are safe.
first-class continuations
call/cc captures the rest of the computation as a value you can store and resume later.
lexical closures
Scope by nesting, not by rulebooks — the modern Lisp core in four keywords.

101 — hello, world

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).

the first program1975
(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.

101 — core concepts

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)))     ;=> 42

03 — tail calls

Proper tail calls are guaranteed: recursion that compiles to a jump, forever.

(define (loop n)
  (if (= n 0) 'done (loop (- n 1))))

201 — going deeper

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.

  1. hygienic macros
  2. call/cc for control flow
  3. records and functional update

hygienic macros

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))]))

call/cc for control flow

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 and functional update

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 specimen — factorial

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.

the continuation1975
(call/cc
  (lambda (k) (k 42)))

;=> 42 — the future itself, as a value

Run it today

installbrew install mit-scheme

runmit-scheme --script fact.scm

Where it is now

Racket (education, research), Guile (GNU scripting), and JavaScript’s closures trace their semantics here.