01 — s-expressions
One syntax for code and data: the program can read, build and run its own code.
(+ 1 (* 2 3)) ; prefix, fully parenthesized
(list 'a 'b 'c) ; data...§ 02 — Eras · 1958
code as data — the programmable programming language
Left: era context, features, and the 101 hello. Right: 3 core concepts, 3 deeper 201 lessons, the factorial specimen, and where LISP lives today — each column scrolls on its own.
Numbers were easy for machines; symbols and recursion were not. LISP was built to compute with ideas — lists, functions, programs.
The parentheses (“lots of irritating superfluous parentheses”), runtime costs that offended the era, and a thousand dialects of the same dream.
Session one is the smallest program that still counts as speaking LISP: what every tutorial prints first, in the dialect that mattered when the language arrived (1958).
(format t "Hello, world~%")101First contact — hello world and 3 ideas that define how LISP 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 LISP. Read the note, then the code — together they are the 101 in one sitting.
01 — s-expressions
One syntax for code and data: the program can read, build and run its own code.
(+ 1 (* 2 3)) ; prefix, fully parenthesized
(list 'a 'b 'c) ; data...02 — car, cdr, recursion
Lists are pairs; walking them taught the world recursion.
(defun len (xs)
(if (null xs) 0
(+ 1 (len (cdr xs)))))03 — eval & quote
Quote suspends evaluation; eval resumes it — metaprogramming in two primitives.
(eval (list '+ 1 2)) ;=> 3
'(+ 1 2) ; the code, unevaluatedThe 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 LISP distinctive at scale.
defmacro writes code that writes code, with backquote and comma controlling what is evaluated when. Every Lisp-family macro system descends from this.
(defmacro unless (test &body body)
`(if ,test nil ,@body))
(unless (null xs)
(car xs))Functions are values: mapcar, reduce and funcall pass behaviour around instead of data. The functional core of Lisp is its calling convention.
(reduce + '(1 2 3 4)) ;=> 10
(mapcar #'1+ '(1 2 3)) ;=> (2 3 4)
(funcall #'+ 1 2) ;=> 3Handlers bind to conditions, and restarts let a handler resume the computation from a chosen point — a control structure nothing else had in 1958.
(handler-case (error "boom")
(error (e) (format t "caught: ~a~%" e)))The conditional, recursion, garbage collection — and code written as the very data structure it manipulates. Nine ideas for one language; all nine still load-bearing.
(cond ((null xs) 0)
(t (+ 1 (len (cdr xs)))))installbrew install sbcl
runsbcl --script fact.lisp
Descendants run airlines (Common Lisp), JVM shops (Clojure), and every lambda you have ever typed in JavaScript, Python or Rust.