# Why Scheme?

> Source: <https://goeteia.dev/why>
> Published: 2026-09-16 04:03:36+00:00

Not because it reads elegantly to a human — because a model can reliably *generate* it, *verify* it, and *manipulate* it.

The bottleneck of AI-written code isn't taste — it's trust. A model is strongest at producing **constrained structure** and weakest at **guaranteeing runtime semantics**. Scheme's value for AI is that its structure lines up with the first and hands the second to a machine. That points to an optimum that looks different from the one you'd pick for a human.

`async`, a forgotten `await`. An s-expr is syntactically valid the moment its parens balance — the error surface shrinks by an order of magnitude.`(define-message …)` declaration and the macro expands it to correct code. The model writes intent — short, clear, checkable — and the compiler writes the implementation. That's the division of labour it's least likely to botch.
This is the part that's genuinely specific to AI. Generated code is not to be believed; it has to be *proven*. Scheme makes the proof cheap and automatic.

`write` and compare with `equal?`, so one harness can drive two implementations through identical inputs and check them against each other exactly. The model never `(equal? x (read (open-input-string (write‑>string x))))` is a correctness check the model gets for nothing.
An HTML document is a tree; a stylesheet is a list of selector-and-declaration rules — the exact shapes s-expr was made for. So `(web html)` and its dual `(web css)` are just two pure functions over one representation, and the UI becomes ordinary program data: built and checked the same way as the logic beside it.

`(define lapis "#1550c4")` is one binding shared by CSS and code — computed, reused, checked once — where a stylesheet would leave you copying `var(--x)` strings and hoping they line up.`(define (card radius) …)` factors a family of rules; `(media-down 42 …)` and `(prefixed transform …)` expand the boilerplate. The model writes intent; the expander writes the correct CSS — the same division of labour as homoiconic codegen, now for the UI.`(append base-css page-css)` composes shared chrome with the page's own rules. No preprocessor, no build DSL — just values.
The proof is the page you are on: its markup and every rule in its stylesheet are `site/why.ss`, a Scheme program Goeteia compiled and ran to emit this HTML. The site is built exactly the way the argument says to build it.

The biggest risk in AI-written network code is the protocol: fields out of order, an encoder that doesn't match its decoder, a state machine missing a transition — the kind of thing that only detonates at runtime. Scheme moves it forward in time.

`read` s and `define-json` / `define-message` schema rather than a hand-written codec — and the test checks symmetry directly: `(decode (encode x)) = x`.
Declarative protocol & schema, plus automatic differential and round-trip verification. The model emits short, declarative, structurally-valid *intent* — schemas, routes, `sx` templates; macros produce the implementation; the machine proves it correct. Work lands on the model's strength; risk lands on the verifier.

Models have seen orders of magnitude more JavaScript, so their intuitive recall for it is stronger; writing Scheme leans harder on the verification scaffolding above to catch what recall would have caught for free. JavaScript is the language a model remembers better — but Scheme has the properties that *matter* for code that must be verified anyway, provided you actually build the loop. Here, it's built: differential testing, the self-hosting fixpoint, and read/write round-trips.

And the ecosystem gap is narrower than it looks, because you don't have to leave the JavaScript world to enter Goeteia. Its `(web js)` FFI bridge reaches straight into the host: a port can call into any existing JavaScript library — the whole npm-scale ecosystem stays one call away, seamlessly. You verify the code you write; you borrow, unchanged, the libraries the world already wrote.
