LISP (McCarthy, 1958, running here on a PDP-1 the way it originally ran at MIT) makes a different bet than Forth does. Instead of a stack of numbers, LISP has one universal data shape: the list, written as parentheses around space-separated items. A LISP program is itself just a list — there's no separate "syntax" for code versus data, which is the single strangest and most powerful idea in the language.
(+ 3 4) ; a list: the symbol +, then 3, then 4
; EVAL treats the first item as an operator
; and the rest as its arguments → 7
(+ 3 (* 4 5)) ; nested lists nest naturally
; EVAL: (* 4 5) → 20, then (+ 3 20) → 23
This (operator arg1 arg2) ordering is called
prefix notation, or historically
Polish notation — named for logician
Jan Łukasiewicz, who invented it in the 1920s (in Warsaw,
Poland, hence the name) so that logical formulas could be written
completely unambiguously without any parentheses at all, since
the position of each operator alone determines how the expression groups.
LISP borrowed that ordering but kept the parentheses anyway, to make the
grouping visible to humans and trivial for the reader ("EVAL") to parse.
Under the hood every list is a chain of two-slot cells called
cons cells. CONS builds one,
CAR reads the first slot, CDR reads the rest.
(CONS 1 (CONS 2 (CONS 3 NIL))) ; builds the list (1 2 3) (CAR '(1 2 3)) ; → 1 (CDR '(1 2 3)) ; → (2 3)
| Form | What it does |
|---|---|
(QUOTE x) / 'x | treat x as data, not code to evaluate |
(CONS a b) | build a new cell holding a and b |
(CAR x) | the first element of list x |
(CDR x) | everything after the first element |
(COND (p1 e1) (p2 e2) ...) | the original if/else: first true p, run its e |
(LAMBDA (x) ...) | an anonymous function of x |
Ordinary arithmetic uses infix notation
(3 + 4, operator in the middle), which needs parentheses and
precedence rules (why does 2 + 3 * 4 mean 14, not 20?) to stay
unambiguous. Both LISP and Forth exist specifically to get rid of that
ambiguity, but they throw the operator to opposite ends of the expression:
| Notation | Operator position | Example: (3 + 4) * 5 | Where it shows up here |
|---|---|---|---|
| Infix | between the operands | (3 + 4) * 5 |
ordinary math class; needs parens/precedence |
| Prefix (Polish notation) | before the operands | (* (+ 3 4) 5) |
this page — LISP S-expressions |
| Postfix (Reverse Polish) | after the operands | 3 4 + 5 * |
the FORTH-70 terminal |
Prefix and postfix are mirror images of the same trick: put the operator somewhere fixed relative to its arguments so a reader (human or machine) never has to guess how the expression groups — no parentheses required for the notation itself to be unambiguous. LISP kept the parentheses anyway, as a readability aid and because a parenthesized list turned out to double perfectly as LISP's own data structure. Forth went the opposite direction: no parentheses, no ambiguity, because a stack machine reading strictly left to right never needs to look ahead — by the time it reads an operator, both arguments are already sitting on the stack waiting for it.
Historical note: Reverse Polish notation itself wasn't invented by Forth — it was described by Charles Hamblin in the mid-1950s, drawing on Łukasiewicz's earlier prefix scheme and simply reversing it. Forth (1970) was one of the first popular programming languages to build its entire execution model around it; LISP (1958) is twelve years older and took the prefix branch of the same family tree instead.
See also: 1970 FORTH terminal (postfix / RPN) · 1985 dial-up BBS · 1993 Mosaic homepage · 1991 Gopher menu · return to the surface (WWW homepage)