Why can no scheme assign a distinct finite identifier to every infinite stream of events a system could emit?
answer
- finite identifiers can be put in a list
- same size means a pairing exists
- finite strings are countable, streams are not
- walk the diagonal and disagree
- differs from stream n at position n
basics
~20 sFinite identifiers can be listed one after another, so they reach only countably many things. The infinite streams are uncountable: given any listing, flip the n-th symbol of the n-th stream and you have built a stream the listing missed.
solid answer
~50 sTwo sets have the same size when a bijection between them exists, and a set is **countable** when it can be paired with the positive integers — equivalently, when its elements can be arranged in one endless list. Every scheme handing out distinct finite identifiers is such a list, because the finite strings over a finite alphabet can themselves be ordered by length and then alphabetically. So the question becomes whether the infinite streams form a countable set, and **Cantor's diagonal argument** says they do not. Suppose someone hands you a numbering of all infinite two-symbol streams. Build a new stream `d` whose n-th symbol differs from the n-th symbol of the n-th listed stream. Then `d` differs from every listed stream at a known position, so it was never in the list. The listing was arbitrary, so no listing works. The consequence is structural, not budgetary: no bigger identifier, no larger address space and no better hash changes it.
code
pseudocode · 8 lines// suppose stream(1), stream(2), stream(3), ... numbers every
// infinite stream over the two symbols 0 and 1
for n = 1, 2, 3, ...:
d[n] = 1 - stream(n)[n] // disagree with stream n at position n
// d is an infinite 0/1 stream, and for every n it differs from
// stream(n) at position n -- so d appears nowhere in the numberinggo deeper
Recall the two words and their meanings: countable means the elements can be put in one endless list, and uncountable means no list can reach them all, however long it runs.
Reproduce the construction: given any listing of infinite streams, take the n-th symbol of the n-th stream and flip it, and explain why the result cannot appear anywhere in that listing.
Draw the engineering line. Explain why the obstruction is structural rather than budgetary, and which objects in a real system are finite and nameable versus which are only ever approximated.
Use it to police a requirement's wording: a commitment to identify every possible behaviour is asking for something unattainable, and the right move is to narrow the commitment to recorded, finite artifacts.
## What countable means, precisely The whole argument rests on one definition. Two sets have the **same size** when a bijection between them exists — a pairing that leaves nothing spare on either side. A set is **countable** when such a pairing exists with the positive integers, which is the same as saying its elements can be laid out in one endless list `x1, x2, x3, ...` where every element appears at some finite position. That definition is more generous than intuition expects, and several sets that feel far too big are countable: - The integers, negatives included: list them `0, 1, -1, 2, -2, ...`. - Every **finite string** over a finite alphabet: order by length first, then alphabetically within each length. Each length holds finitely many strings, so every string appears at a finite position. - Therefore every **finite artifact** a system can hold — every log file, every configuration, every identifier scheme's output, every finite program text — is countable, because each one is a finite string over a finite alphabet. That last point is what makes identifier schemes work at all: handing out distinct finite identifiers *is* building such a list. ## The diagonal argument Now take the set of **infinite** streams over even a two-symbol alphabet — an endless sequence of events where each step is one of two kinds. Suppose someone claims a numbering of all of them: `stream(1), stream(2), stream(3), ...`. Build a new stream `d` by walking down the diagonal of that list and disagreeing at every step: let `d`'s n-th symbol be the opposite of `stream(n)`'s n-th symbol. - `d` is a legitimate infinite stream over the same alphabet — every position has a defined symbol. - `d` differs from `stream(1)` at position 1, from `stream(2)` at position 2, and in general from `stream(n)` at position n. - So `d` is not `stream(n)` for any n, and the numbering was not complete. Nothing about the numbering was assumed, so **no** numbering is complete: the streams are **uncountable**. They cannot be paired with the positive integers, and so cannot be paired with any set of finite identifiers either. ## Why this is structural and not a budget problem The usual objection is that a longer identifier would fix it. It would not, and stating why is the point of the question: - Identifiers of some fixed maximum length form a finite set; identifiers of any finite length form a countable one. Neither reaches an uncountable set. - Nothing here is about machine word sizes, storage, or how long the system runs. The argument is about the sets, so faster hardware and bigger addresses move nothing. - It also does not depend on the alphabet: two symbols per step already suffice, so a richer event vocabulary cannot rescue the scheme. ## What an engineer actually takes away 1. **Identify finite artifacts, not behaviours.** A trace you have recorded is finite and can be named. "Every possible behaviour of this system, forever" is a different kind of object and cannot be enumerated. 2. **Any finite identifier over an unbounded input domain is many-to-one.** That is a counting fact rather than a flaw in a particular scheme, and it is why a fixed-width identifier over an open-ended input space can only ever be distinct in practice, never distinct by construction. 3. **Continuous quantities carry the same warning.** Anything modelled as an arbitrary real value — an exact instant, an exact ratio — sits in an uncountable set, which is one reason such values are always stored as a finite approximation with a stated precision rather than as themselves. ## The refinement worth knowing Here is the fact that separates a recited proof from an understood one. Every stream a **program** can produce is itself named by that program's finite text, and finite texts are countable. So the streams your systems will ever generate form a countable set; the uncountably many others are exactly those with no finite description at all. The impossibility is therefore not an obstacle to any identifier scheme you were actually going to build — it is a statement about what "every possible stream" quietly asks for. Interviewers like that turn because it shows you can tell the mathematical claim apart from its engineering reach, rather than treating an uncountability result as a warning about running out of identifiers.
- Why does a longer identifier, or an unbounded one, not solve this?Identifiers of one fixed length form a finite set, and identifiers of any finite length form a countable one, because they can be ordered by length and then alphabetically. Countable is exactly what the diagonal argument defeats, so extending the length changes the size of the finite case but never the kind of the infinite one. The obstruction is the structure of the two sets, not the width of the identifier.
- Are the streams a real system can actually produce uncountable too?No, and this is the useful refinement. Any stream generated by a program is described by that program's finite text, and finite texts are countable, so the producible streams form a countable set. The uncountably many remaining streams are precisely those with no finite description. The impossibility result therefore constrains the phrase every possible stream, not any identifier scheme you were realistically going to build.
- What does the diagonal argument actually prove: that no injection exists, or that no surjection does?That no surjection from the positive integers onto the streams exists — no listing reaches them all, since the diagonal stream is always missed. An injection the other way is easy, so the streams are strictly larger. Stating it as the missing surjection is the precise form; saying only that the two sets cannot be paired is true but loses which half of the pairing fails.
Every finite log file can be given a page number the way every word gets a page in a dictionary. An endless stream is not a word in that dictionary, and the diagonal trick constructs one that is missing from any dictionary you could print.
saying these in an interview costs you the question
- Says a wider identifier would eventually cover every stream
- Treats uncountable as merely a very large finite number
- Thinks finite strings over a finite alphabet are uncountable too
- Builds the diagonal stream by copying instead of disagreeing
- Claims the result depends on the alphabet having many symbols
- Assumes the streams a program can produce are uncountable as well