A document editor keeps past versions in a persistent structure - after an edit, what can an old reference still do?
answer
- old versions do not die
- ephemeral is the opposite word
- the update returns something
- not storage, versions in memory
- previous handle still fully readable
basics
~20 sA persistent structure never destroys the version an update was applied to. The edit returns a new version, and a reference taken earlier still reads exactly the document it read before, with no copy having been taken.
solid answer
~40 sPersistent means every version stays valid after an update. The edit is a function from version to version: it returns `v2` and leaves `v1` completely usable, so the undo stack, a background spell-checker mid-pass and a diff view can all keep reading `v1` while editing continues on `v2`. Nothing was snapshotted and nothing was invalidated - the old handle is the real document, not a defensive copy of it. The contrast is an *ephemeral* structure, the ordinary mutable kind, which holds one state that each write overwrites, so anything wanting the previous text had to copy it beforehand. Persistence here means versions stay addressable in memory; it says nothing about writing to storage.
code
pseudocode · 11 lineslet v1 = document with lines ["alpha", "beta"]
let v2 = replaceLine(v1, 1, "BETA") // returns a NEW version
print lineAt(v1, 1) // "beta" - v1 was not touched
print lineAt(v2, 1) // "BETA"
undoStack.push(v1) // v1 is a usable document, not a saved copy
let v3 = replaceLine(v2, 0, "ALPHA")
print lineAt(v1, 0) // still "alpha"go deeper
Recall the one-line guarantee: an update returns a new version and the old one stays readable. Always bind the returned value - the version you passed in is intentionally unchanged.
Explain the contrast with an ephemeral structure and why old versions are not copies: the update rewrites only what it changed and both roots reach everything else. Name the three distinct promises - immutable value, persistent structure, read-only handle.
Show where the guarantee earns its keep in a running system: snapshot reads with no lock and no copy, handing a version to another worker safely, undo as a list of roots. Then name the bill - every retained version retains what it can reach.
Frame it as a system property, not a collection choice: adopting versions-as-values changes how state is published, how history is bounded and how teams reason about concurrent readers. Decide where the boundary of that model sits before the memory profile decides for you.
## What the word promises A data structure is **persistent** when an update leaves the version it was applied to intact and still usable. The structure persistence is defined against is called **ephemeral**: it holds exactly one state, and every write destroys the state before it. The word is unfortunate, because it has nothing to do with durable storage - nothing here is written to a file. It means **versions stay addressable in memory**. Take the setting concretely. An editor holds document version `v1`. A keystroke produces `v2`. In an ephemeral buffer the keystroke rewrites the text in place, so whatever wanted the previous state had to have copied it first - that is exactly what a hand-rolled undo stack is. In a persistent document the edit *returns* `v2`, and `v1` remains a complete, readable, queryable document that anything still holding it may keep using. ## What an update actually hands back Three consequences follow directly from the definition: - **The update is a function from version to version.** Its result is the new version. If you ignore the return value, nothing you can observe has changed - a classic beginner bug against this kind of structure. - **The old handle is not a snapshot.** No copy was taken on its behalf. It is the same version object it always was; the update simply did not touch it. - **Nothing is invalidated.** There is no equivalent of an iterator that blows up because someone wrote to the collection underneath it, because nobody can write to a version at all. ## Persistent, immutable, read-only: three different promises These three get used interchangeably and mean different things. | term | what it actually constrains | |---|---| | immutable value | this value's own fields never change after it is constructed | | persistent structure | an update yields a new version and every earlier version stays valid | | read-only view | the holder of *this* handle cannot write through it; someone else still might | A persistent structure is normally built out of immutable nodes, so the two travel together, but they answer different questions: immutability is about one value, persistence is about the *family of versions* an update generates. A read-only handle over an ephemeral structure gives you neither - the data can still change under you, you are just not the one changing it. ## Why keeping the old version is affordable The naive way to keep every version is to copy the whole document per keystroke, which is quadratic in the session and obviously unusable. Real persistent structures avoid it by rewriting only the nodes on the route from the root to the slot that changed and pointing the new root at them; every part the edit did not touch is reachable from both roots at once. That is why holding `v1` and `v2` together costs far less than two documents - though it is not free, and a structure small enough that its whole body sits on the changed path really is copied end to end. ## What the guarantee buys in practice - **Undo and redo become trivial.** The history is a list of roots; undo is picking an earlier one, not replaying inverse operations. - **Snapshot reads need no lock and no copy.** A long-running word count can walk `v1` to completion while the user types into `v9`. - **Handing a version to another worker is safe by construction.** There is nobody who could mutate it while the worker reads. - **Comparing two versions is a normal traversal**, because both versions genuinely exist. ## What it costs, honestly - **An update is more than a memory store.** It allocates the nodes along one path and touches scattered memory, where an in-place write touches one slot. - **A retained version retains its nodes.** Every root you still hold keeps everything it can reach alive; an unbounded history is an unbounded memory bill. - **The guarantee is only as deep as the structure.** If a version's slots hold handles to something mutable, the version is fixed but what it points at need not be. ## How to check the claim When someone says a structure is persistent, three questions settle it: *what does an update return?* *Can I still read the handle I had before it?* *Can I still update that older handle?* A structure that answers the first two but not the third is persistent in the weaker, partial sense - all versions readable, only the newest one extendable - which is often exactly what an editor needs and sometimes not enough.
- A developer calls the update and then reads the same handle they passed in, and sees no change. What did they get wrong?They treated the update as a command when it is a function. The update produces a new version and returns it; the version passed in is deliberately untouched. The fix is to bind and use the returned version - ignoring the result of an update against a persistent structure is always a bug, never a no-op you can shrug at.
- Does calling a structure persistent tell you anything about what its elements can do?No. Persistence constrains the structure's own versions: each one stays valid after an update. If a version's slots hold handles to objects that can still be changed, the version's shape is fixed while the data reachable through it is not. That distinction is separate from persistence and has to be checked on its own.
- Why is 'persistent' a confusing name for this property?Because the same word is used elsewhere for data that survives a process restart on durable storage. Here it means only that earlier versions survive an update in memory. A persistent structure disappears with the process like any other in-memory value; the persistence is across *versions*, not across *runs*.
A bound ledger written only on fresh pages: you never scribble over an old entry, so a bookmark placed last week still lands on exactly what it named, and the newest page is simply further on.
saying these in an interview costs you the question
- Thinks persistent means saved to disk between runs
- Says the old reference now sees the updated data
- Assumes the update mutated in place and returned nothing useful
- Believes keeping the old version required a full copy first
- Cannot separate a read-only handle from an unchangeable version
- Assumes retaining a version costs nothing