Setting the Stage: A World of Accidental Languages
Before Landin, programming languages weren’t really designed — they just happened.
You had hardware constraints. A deadline. Maybe a maths professor with a punch card habit. FORTRAN helped engineers do maths. COBOL kept bureaucrats happy. LISP? Pure theory. Rough edges.
Most languages bent to the machine, not the mind. Syntax was whatever worked. Semantics were implied. Early FORTRAN? Numbers, jumps, silent conventions — code more like incantation than conversation.
The idea that a language could be a designed object — with care, intention, even philosophy — hadn’t quite landed.
Landin saw something different. To him, code wasn’t just commands — it was notation. And notation wasn’t just a surface. It was thought, made visible. And if it shaped how we think, it needed looking after.
He didn’t see languages as mere tools for machines. He saw them as reflections of reasoning — scaffolding for thought.
graph LR A(🖥️ Machine-shaped<br>decomposition) B(🧠 Mind-shaped<br>decomposition) style A fill:#eeeeee,stroke:#2e3440,stroke-width:1.5px style B fill:#b2dfdb,stroke:#2e3440,stroke-width:1.5px A -- 🔍 Lens of notation ---> B
That was the turn. Not a tweak to syntax — a shift in purpose.
If code is how we express thought, then design choices start to shape the thinking itself. And for Landin, it all started with a better question:
What if we stopped layering features, and started from meaning?
ISWIM, Lambda Calculus, and the Power of Less
Landin wasn’t pitching a new language. He was questioning what a language even is.
At the heart of The Next 700 Programming Languages is a bold idea: that most languages — with their loops, operators, and type systems — are just ergonomic façades. Underneath it all lies something far simpler and more powerful: the lambda calculus. Just variables, functions, and substitution. No loops. No types. No side effects. And yet, it can express anything a Turing machine can.
To most, lambda calculus was theory. Landin saw it as foundation. He asked: what if we started there? Not to restrict, but to clarify.
His answer was ISWIM — a fictional language, never built, but deeply influential. It existed to expose assumptions, not to execute code.
ISWIM stripped things back and asked what we really need. Turns out, most features are just there to make things more pleasant. And those conveniences matter — but only when we know what’s underneath.
%%{init: { "theme": "base", "themeVariables": { "fontSize": "18px", "fontFamily": "monospace", "textColor": "#2e3440", "edgeLabelBackground": "#ffffff" } } }%% flowchart BT subgraph Core A[Lambda Calculus<br><sub>Variables, functions, substitution</sub>] end subgraph Ergonomics B[Syntactic Sugar<br><sub>Loops, infix ops, method calls</sub>] C[Surface Syntax<br><sub>What we see and type</sub>] end Core --> B --> C style A fill:#4DB6AC,stroke:#2e3440,stroke-width:1.5px style B fill:#FFD54F,stroke:#2e3440,stroke-width:1.5px style C fill:#FFAB91,stroke:#2e3440,stroke-width:1.5px
That’s where Landin gave us a phrase we still use: syntactic sugar. Sugar doesn’t change what code can do. It changes how it feels. It smooths the surface — but sometimes, it also hides the structure.
When Code Feels Right (and That’s the Problem)
We like code that reads clean. That flows. That feels like the thing it’s doing.
That’s what syntactic sugar gives us — not power, just ease. a + b
feels like arithmetic, but it’s just add(a, b)
with a prettier face. Same with obj.method(arg)
— function calls in disguise. Loops that look simple but mask recursion or side effects. These sugar coatings lull us into fluency, which often becomes false confidence.
Code | What it hides |
---|---|
for (i = 0; i < n; i++) | It’s recursion, just flattened |
obj.method(arg) | It’s a function, wearing OO clothes |
a + b | It’s add(a, b) , but sweeter |
We breeze past code that looks familiar — until it breaks in subtle ways. Because once something feels readable, we stop asking if it’s true.
This isn’t just about sugar. It’s about how our brains work. We’re wired to fill in blanks, to pattern-match fast. Great in real life. Risky in code. Especially when the syntax nudges us to trust what we haven’t really understood.
Take this snippet:
array.filter(x => x.active).map(x => x.id)
It feels fluent. Feels safe. But under the hood? Implicit assumptions about nulls, ordering, short-circuiting — all papered over by a nice tidy surface. What looks obvious often isn’t.
ORMs are another classic case. You write user.posts
and it feels like you’re accessing a field. But that one line might trigger a query, or a dozen. It might eager load, lazy load, or silently blow out to a join explosion. That one line? It looks like data — but behaves like a contract with a remote system.
The notation feels local.
The behaviour is anything but.
%%{init: { "theme": "base", "themeVariables": { "fontSize": "18px", "fontFamily": "monospace", "textColor": "#2e3440", "edgeLabelBackground": "#ffffff" } } }%% graph LR A[Raw Problem] B[Human Interpretation] C[Chosen Notation] D[Misleading Confidence] E[Accurate Mental Model] A --> B --> C --> D B --> E style A fill:#CFD8DC,stroke:#2e3440,stroke-width:1.5px style B fill:#CFD8DC,stroke:#2e3440,stroke-width:1.5px style C fill:#CFD8DC,stroke:#2e3440,stroke-width:1.5px style D fill:#FF8A65,stroke:#2e3440,stroke-width:1.5px style E fill:#A5D6A7,stroke:#2e3440,stroke-width:1.5px
Landin’s insight was that notation isn’t just cosmetic. It’s scaffolding. If it’s solid, it holds our thinking. If it’s warped, everything we build on top bends with it.
The Cultural Inertia of Tools
Languages shape more than programs — they shape people.
Use a tool long enough, and it becomes more than a way to get things done — it becomes a way of seeing. The syntax starts to feel like truth. The idioms feel like best practice. The friction points turn into inside jokes.
Perl had a culture. Ruby preached a philosophy. JavaScript turned into a diaspora.
That’s the shift Landin anticipated. If language is notation, and notation shapes thought, then language design isn’t just technical — it’s sociological. It determines how teams communicate, what they optimise for, what gets taught, what gets forgotten. Syntax is just the start. Everything from package managers to lint rules becomes part of the lived experience.

Most languages don’t succeed because they’re the best design. They succeed because they build habits, communities, and defaults. And once those are in place, change starts to feel like breaking the rules — even if the rules never made sense in the first place.
That’s the cultural cost of tools. They don’t just encode logic. They encode values.
DSLs, LLMs, and the Next 700 Mistakes
We didn’t stop inventing languages. We just got sneakier about it.
Now they hide in plain sight — YAML for infrastructure, HCL for provisioning, “SQL-ish” configs for data pipelines. They wear the costume of data, so we treat them like harmless markup. But open one up, and it’s all branching logic, side effects, magical defaults, and comments pleading with the next developer not to touch anything.
They’re not inherently broken. But they weren’t exactly built to be understood. Most of them favour quick writing over long-term reasoning. They’re sugary and forgiving — right up until they’re not.
And just when we started to get a handle on them, LLMs entered the party. Now we’ve got synthetic DSLs being generated on demand — plausible-looking configs with the structural integrity of fairy floss. The code reads fine, until you try to run it and something silently disappears.
graph TD A[🧠 Fluent Surface Syntax<br><sub>Looks right, feels easy</sub>] --> B[✅ False Confidence<br><sub>It must be correct</sub>] B --> C[🚫 Missed Meaning<br><sub>Ambiguity, inconsistency</sub>] C --> D[🐞 Human Bugs<br><sub>Quiet misbehaviour</sub>] C --> E[🤖 LLM Hallucinations<br><sub>Code without grounding</sub>]
The real issue isn’t the number of DSLs. It’s how casually we pretend they’re not languages — no semantics, no spec, just good intentions and tab spacing.
They don’t look like code, but they act like it — with structure, side effects, rules, and surprises. Because they resemble data, we often don’t give them the care real languages demand.
They fail like code.
They demand design like code.
Landin didn’t call for minimalism. He just wanted us to take language seriously — to design it like it mattered, because it does.
Compositionality as a Systems Superpower
For all the talk of syntax, Landin’s real focus was shape — the structure beneath the surface.
ISWIM wasn’t built to impress. It was built to hold together. Small, yes. But sturdy enough to build on without it collapsing. It never needed to be a language — just something solid enough to build on.
That’s what compositionality gives you: designs that stay stable under pressure. Systems where you can add one piece without rewriting the rest. Where understanding grows instead of unravels.
You’ve seen it: UNIX pipes. HTML and CSS. React components. Terraform modules.
They weren’t flawless. But decades later, they’re still standing.
The fragile ones? Usually the clever ones.
Clever, sure — right up to the moment you try to extend it.
graph TD subgraph Fragile A[🧠 Clever Solution] --> B[🕸️ Hidden Coupling] B --> C[🚨 Breaks on Change] end subgraph Resilient D[🧩 Composable Parts] --> E[📏 Clear Boundaries] E --> F[🧬 Survives Change] end style A fill:#ffe082,stroke:#2e3440,stroke-width:1.5px style B fill:#ffab91,stroke:#2e3440,stroke-width:1.5px style C fill:#ef9a9a,stroke:#2e3440,stroke-width:1.5px style D fill:#a5d6a7,stroke:#2e3440,stroke-width:1.5px style E fill:#81c784,stroke:#2e3440,stroke-width:1.5px style F fill:#66bb6a,stroke:#2e3440,stroke-width:1.5px
Compositional systems age well because the pieces don’t fight. You can replace a chunk without relearning the whole. Boundaries stay intact. Brains stay sane.
That was ISWIM’s real legacy — not minimalism, but shape.
Primitives that stacked.
Bricks with edges you can align — not amorphous blobs.
The 701st Language
It’s easy to want the next one. A cleaner syntax. Fewer footguns. Something that feels right without getting in the way. Maybe this time the abstractions will hold. Maybe the layers won’t leak.
But that was never really Landin’s focus. He wasn’t chasing cleaner tools — he was tracing how tools shape the way we think. He started with notation, but the idea runs deeper. You can see it in how we design APIs, shape architectures, set boundaries.
Every choice has a gravity to it. Some pull toward fluency — fast to write, easy to adopt, hard to question. Others pull toward structure — slower, maybe, but easier to extend, easier to trust.
%%{init: {"themeVariables": {"fontSize": "16px", "fontFamily": "monospace"}} }%% graph TB A[🧭 Design Starting Point] subgraph "Familiar Fluency" B[🎭 Syntactic Sugar] C[⚡ Fast Onboarding] D[🚨 Accidental Constraints] E[♻️ Layered Hacks] F[🕳️ Complexity Spiral] end subgraph "Composable Structure" G[🔍 Reflect on Notation] H[🧰 Design Primitives] I[🧩 Compose Thoughtfully] J[🛠️ Sustainable Extension] K[🌱 Systems That Grow Well] end A --> B A --> G B --> C --> D --> E --> F G --> H --> I --> J --> K style B fill:#ffe0b2,stroke:#f57c00,stroke-width:1.5px style G fill:#c8e6c9,stroke:#388e3c,stroke-width:1.5px
Landin didn’t give us a template. He gave us a lens — to see when the defaults are steering us, and to design with shape in mind. Not just for elegance. For endurance.
For systems that stay legible as they grow.