Skip to the reading
QuodlibetA deep study · self-reference in computation

The fixed point that lets a program read its own code

The Quine

Write a program that prints its own source, exactly, with no input. It sounds like a trick, and it is a theorem — a special case of the deepest fact about computation's self-reference, Kleene's recursion theorem: every effective transformation of programs has a program that is its own transform. A program may be written to hold and use its own code, always. This is Lawvere's diagonal made effective — the same fixed point that gives the λ-calculus its Y combinator and arithmetic its Gödel sentence, now in the theory of computation. And like every appearance of that fixed point in the corpus, it faces two ways: it grants a program self-knowledge, and in the same breath it forbids any program from deciding what another computes. Rice's theorem is the recursion theorem's shadow, and this study builds both from the one construction.

the self-referential program · the recursion theorem · the quine · the diagonal lemma's twin · Rice · self-reproduction · the fixed point that computes itself

A quine is a program that outputs its own text. The name honors the logician who studied self-reference, and the artifact is a small marvel — no input, no file access, just a program that, run, reproduces itself character for character. One's first instinct is that it should be impossible, or a cheat; it is neither. It is a corollary of a theorem that sits at the exact center of the corpus, in the computational key.

Kleene's recursion theorem says that self-reference is not a trick but a guarantee: for any computable way of transforming programs into programs, there is a program whose meaning is unchanged by the transformation — a fixed point in the space of programs. Feed it the transformation “replace me by a program that prints my own code,” and the fixed point is a quine. Feed it others, and you get programs that reason about themselves, reproduce themselves, or modify themselves. The theorem is the third face of the fixed point the corpus tracks everywhere: the Y combinator is its shadow in the λ-calculus, Gödel's diagonal lemma its shadow in arithmetic, and Kleene's theorem its shadow in the theory of computation — all one construction, Lawvere's diagonal, wearing three costumes. This study proves the theorem and runs a real quine; it lays the theorem beside the diagonal lemma to show them identical; and it derives Rice's theorem — that no non-trivial property of what a program computes is decidable — from the very self-reference that made the quine possible, so that the construction which grants a program its own code is the same one that forbids any program from reading the code of another. Power and limit in a single move: the signature of the diagonal, in the place where programs run.

I · the self-referential program

Can a program hold itself?

Gödel built a sentence that refers to itself — that says, of its own code, that it is unprovable. The computational question is the exact parallel: can a program refer to itself, obtain and use its own text? It sounds circular to the point of impossibility. It is instead guaranteed, always, by a single theorem.

The sharpest form of the question is the quine: a program that, given no input, prints its own source code exactly. The naive objection is a regress — to print my code I must contain my code, but that code must contain the code that prints it, which must contain… — and the regress looks fatal. It is not, because a program can compute its own text rather than store it: a short description that, run, unfolds into itself. The mechanism that makes this always possible is Kleene's recursion theorem, and it is the computational incarnation of the fixed point that runs through the whole corpus.

two self-references, one theorem

Gödel's diagonal lemma is the syntactic version: for any property ψ, there is a sentence that asserts ψ of its own Gödel number. Kleene's recursion theorem is the computational version: for any transformation of programs, there is a program that behaves as the transformation says of its own index. The first gives arithmetic a sentence that talks about itself; the second gives computation a program that acts on itself. They are not analogous — they are the same theorem, Lawvere's diagonal, in two settings, and this study will make the identity exact.

II · the recursion theorem

Every transformation has a fixed-point program

Kleene's theorem is a fixed-point statement about programs. Transform programs however you like, so long as the transformation is itself computable, and some program will be left unchanged in meaning — a program equal to its own transform. Its proof is the diagonal self-application, the λx.x x of the corpus, carried out on program indices.

Fix a programming language and let φe be the function computed by the program with index e. A transformation of programs is a total computable map f on indices — given a program, it returns another. The theorem says f cannot change every program's meaning.

Kleene's recursion theorem (1938)
For every total computable function f, there is an index e with
φe = φf(e)
The program e and its transform f(e) compute the very same function. Equivalently — the self-reference form — any program may be written so as to use its own index as data: whatever a program could do given its own source, some program does.

the proof is the diagonal  The s-m-n theorem lets us, from any computable recipe, effectively produce a program-index carrying out that recipe. Use it to build a total computable function d such that, for every index x, the program d(x) computes “first run program x on its own index x to get a number, then run f of that, then run the resulting program on the real input.” In symbols φd(x) = φf(φx(x)) whenever φx(x) is defined. Since d is itself computable, it has an index a — a program with φa = d. Now feed d a code for itself: set e = d(a), which is φa(a), the program a run on its own index. Then φe = φd(a) = φf(φa(a)) = φf(d(a)) = φf(e). The fixed point is d applied to a code for itself — the self-application φa(a), precisely the λx.x x that builds the Y combinator, here performed on indices and made effective by s-m-n. Lawvere's diagonal, computing.

III · the quine

A program that prints itself

Feed the recursion theorem the transformation “replace a program by one that prints that program's source,” and the fixed point is a program that prints its own source. Here is a real one — not stored text echoed back, but a program that computes its own listing from itself. Run it and compare.

The recursion theorem does not merely assert a quine exists; it tells us how to get one. Let f transform each program into a fixed program that ignores its input and prints the source of the index it was handed. A fixed point of that f — an e with φe = φf(e) — is a program that ignores its input and prints its own source. Below, the same idea realized directly: a function that reconstructs the exact expression that defines it, so that running the program yields the program.

the program — its own complete source
A self-reproducing program. The function names itself, and its body reconstructs the exact source expression that defines it — so its output is its own text, character for character. No input, no stored copy: the listing is computed from the program itself, which is what the recursion theorem guarantees can always be done.
the deeper reproduction

Self-reproduction is older and larger than the quine. Von Neumann, seeking to understand how a machine could build a copy of itself without infinite regress, designed a universal constructor paired with a description of itself — the machine reads its own blueprint, builds a copy, and copies the blueprint into it. The logical heart of that design is the recursion theorem: a system with access to its own description can act on it, reproduction included. Biology runs the same architecture — a cell's machinery reads the DNA that describes that machinery, and copies both. The quine is the barest expression of a principle that reaches from a one-line program to the logic of life: a self-description, used.

IV · the diagonal lemma's twin

The same theorem, three times

The recursion theorem is not like Gödel's diagonal lemma and the Y combinator; it is them, in a third setting. Each is a construction that, from a self-application, manufactures a fixed point of a given operation — self-reference guaranteed. The corpus's thesis is that all three are Lawvere's theorem, and here the three stand together.

Line up the statements and the sameness is plain. In each, an arbitrary operation is given, and a self-referential object is produced whose relation to the operation is a fixed-point equation.

arithmetic — Gödel  For any formula ψ(x), the diagonal lemma builds a sentence φ with φ ↔ ψ(⌜φ⌝) — a sentence asserting ψ of its own code. Take ψ = “not provable” and φ is the Gödel sentence.

the λ-calculus — Curry  For any term f, the combinator Y builds a term Y f with Y f = f (Y f) — a term equal to f of itself. The engine is λx.x x, self-application.

computation — Kleene  For any transformation f, the recursion theorem builds a program e with φe = φf(e) — a program equal in meaning to its own transform. The engine is d(d), self-application again.

Gödel's sentence, Curry's term, and Kleene's program are one fixed point in three notations. Lawvere's theorem states the common core once and for all: in any cartesian closed category, a point-surjective map A → Bᴬ forces every endomap of B to have a fixed point, and the fixed point is built by precomposing with the diagonal A → A×A. Gödel's numbering is such a surjection for definable properties, so “not provable” gets its fixed point — the unprovable truth. The untyped λ-calculus is such a surjection for its own terms, so every f gets its fixed point — general recursion. A universal program is such a surjection for computable functions, so every transformation gets its fixed point — the self-referential program, quine and all. The self-reference that looked like a trick in each setting is the same theorem refusing, in each setting, to let a diagonal escape. What differs is only the price: in arithmetic the fixed point is an undecided sentence, in the λ-calculus a non-terminating term, in computation an uncomputable boundary — three costs of one construction, and the last is Rice's theorem.
V · Rice

The shadow of self-reference

The recursion theorem grants a program access to its own code. In the same stroke it forbids any program from deciding what another computes — for a decider could be turned against a program built, by the recursion theorem, to defy it. Rice's theorem is the sweeping consequence: every non-trivial question about a program's behavior is undecidable.

Distinguish two kinds of question about a program. Syntactic questions ask about its text — how long it is, what symbols it uses, whether it halts within a fixed number of steps — and many are decidable, by inspection. Semantic questions ask about the function it computes — whether it ever halts, whether it computes the identity, whether its domain is infinite — and these are about φe, not about e. Rice's theorem concerns the second kind.

Rice's theorem (1953)
Let P be any property of computable functions that is non-trivial — held by some computable functions and not others — and semantic — depending only on the function computed, not the program computing it. Then the set of programs whose function has P is undecidable. No non-trivial property of a program's behavior can be decided by any program.

the proof is again the diagonal  Suppose some non-trivial semantic P were decidable. Pick a program a whose function has P and a program b whose function lacks it. Now, by the recursion theorem, build a program e that obtains its own index, asks the decider whether its own function has P, and then deliberately computes the wrong one — behaving like b if the decider said “yes,” like a if it said “no.” Then e's function has P exactly when the decider says it does not. The decider is wrong about e — so no such decider exists. The recursion theorem, which built the quine, here builds the program no analyzer can classify.

Decidable or not? The line does not fall where intuition expects. Questions about the program text — its length, a bounded run — are decidable; the trivial semantic question is decidable because its answer never changes. But every non-trivial question about the function computed is undecidable, by Rice — the halting problem is merely the most famous instance, not a special difficulty.
VI · the constructive reach

What self-access builds

The quine is the smallest thing a program can do with its own code. The recursion theorem's real yield is larger: recursion itself, self-modification, and reflection all flow from the single primitive of self-access, and the corpus's constructive fixed point — the Y combinator — is exactly this theorem in the language of terms.

recursion for free  The recursion theorem supplies recursion where a language has none. To define a function that calls itself, one need not have a built-in recursion construct: write the body as if it could name its own index, and the theorem guarantees an index that satisfies the definition. A factorial that “calls itself” is an index e for which φe uses e in its recursive call — a fixed point the theorem produces. This is why the untyped λ-calculus, with no primitive recursion at all, computes every computable function: Y is the recursion theorem in term form, manufacturing the self-reference that recursion needs.

self-modification and reflection  A program with its own text can do more than reprint it. It can analyze itself, transform itself, and run the transformed version — the basis of reflective and self-optimizing systems. It can also underwrite one of computing's stranger facts: a compiler can be written to reproduce a hidden behavior in its own output when it compiles itself, with no trace in the source it is given, because the recursion theorem lets a program build its successor to contain what the source does not show. Self-access is a genuine capability, and like all real capability it cuts both ways.

the double theorem

Self-reference generalizes to mutual reference. The double recursion theorem gives, for any two transformations, a pair of programs each with access to both indices — two programs that know each other and themselves, satisfying a simultaneous fixed-point equation. It is the computational form of the mutual self-reference behind the subtler paradoxes — the two-card Liar, where each of two sentences speaks of the other — and the guarantee that even interlocking self-reference is always realizable in code. What the diagonal grants, it grants in every degree of entanglement: one program that holds itself, two that hold each other, and no upper bound on the knot.

VII · the fixed point that computes itself

Where computation rejoins the diagonal

The recursion theorem is Lawvere's fixed point in the category of computable functions — the diagonal λx.x x made effective, guaranteeing every effective transformation a program it cannot change. It is the corpus's central object seen a third time, and it wears the corpus's central signature: the same construction grants power and imposes limit, in one move.

Gather the two faces. From the fixed point flow the quine, self-reproduction, reflection, and recursion itself — a program may always hold and use its own code. From the same fixed point flows Rice's theorem — no program may decide what another computes, because any decider is defeated by a program built to contradict it. The capability and the impossibility are not opposed findings; they are one theorem read for what it gives and for what it costs.

Self-reference is not a paradox to be avoided but a theorem to be used — and its use has a fixed price. The corpus reads every limit as a diagonal forbidding a fixed point; the recursion theorem completes the picture by showing the diagonal, in the setting of computation, granting one. A program that reads its own code is the affirmative form of exactly the construction that, turned against a would-be decider, proves the halting problem and Rice's theorem — the power to reflect and the impossibility of analysis are the two readings of a single self-application. This is why the corpus insists the results are one. Gödel's sentence that speaks of its own unprovability, Curry's term equal to a function of itself, and Kleene's program that computes with its own index are the same fixed point in the three great settings — proof, reduction, and computation — and in each the fixed point is generous and strict in the same instant: it hands the system a way to refer to itself, and it forbids the system to stand outside itself and decide. The quine that prints its own source and the boundary no analyzer can cross are the near and far sides of one small, inexhaustible fact — that a diagonal, given room to run, always finds its fixed point, and that finding is at once the system's deepest power and its permanent horizon.

A program that prints its own source looks, the first time, like sleight of hand — surely it must peek at a file, or store a copy. It does neither. It computes its own text from itself, and the reason it can is the reason the corpus keeps returning to a single theorem: a diagonal, applied to itself, produces a fixed point, and here the fixed point is a program whose meaning survives its own transformation. Feed that guarantee one instruction and it gives a quine; feed it another and it gives recursion, or a machine that builds a copy of itself, or a system that reasons about its own code. And feed a would-be decider the same guarantee, and it gives the program the decider cannot classify — Rice's theorem, the halting problem, the boundary of analysis. The power to hold oneself and the impossibility of surveying oneself are one construction, generous and strict in the same breath. The quine is the corpus's fixed point in its friendliest costume — not a paradox, not a limit felt as loss, but a small program that, run, hands you itself — and behind that plain gift stands the whole of the diagonal: the reason a system can turn to face itself, and the reason it can never see around its own back.