parity: 19 sentences, two independent implementations
01-npm-registry versions.* py 288 R 288 keys 1.0.0 ok
01-npm-registry versions.*.dependencies.* py 4,645 R 4,645 keys 1.0.0|connect ok
02-hn-thread children.* py 25 R 25 keys 0 ok
02-hn-thread children** py 335 R 335 keys 0 ok
03-natural-earth features.* py 241 R 241 keys 0 ok
05-fhir-bundle entry.*.resource py 564 R 564 keys 0 ok
15-github-issues * py 100 R 100 keys 0 ok
16-movie-ratings *.* py 38 R 38 keys 0|12 Strong ok
17-openlibrary docs.* py 200 R 200 keys 0 ok
19-chicago-salaries * py 5,000 R 5,000 keys 0 ok
05-fhir-bundle . py 1 R 1 keys - ok
01-npm-registry where(url) py 806 R 806 10 shapes MISMATCH
py (10, 806, 'versions.<key>.dist.tarball|288')
R (7, 806, 'versions.<key>.<key>.url|325')
01-npm-registry where(email) py 3,389 R 3,389 8 shapes MISMATCH
py (8, 3389, 'versions.<key>.contributors.[].email|1532')
R (11, 3389, 'versions.<key>.<key>.[].email|2370')
02-hn-thread where(date) py 336 R 336 13 shapes ok
05-fhir-bundle where(url) py 5,511 R 5,511 42 shapes MISMATCH
py (42, 5511, 'entry.[].resource.item.[].adjudication.[].category.coding.[].code|1104')
R (44, 5511, 'entry.[].resource.<key>.[].adjudication.[].category.coding.[].code|1104')
07-graphql-introspection where(empty) py 3,461 R 3,461 43 shapes ok
10-wikidata where(url) py 1,583 R 1,583 10 shapes MISMATCH
py (10, 1583, 'entities.Q30.claims.<key>.[].references.[].snaks.<key>.[].datavalue.value|700')
R (22, 1583, 'entities.Q30.claims.<key>.[].references.[].snaks.P854.[].datavalue.value|679')
13-package-lock where(url) py 1,996 R 1,996 5 shapes ok
16-movie-ratings where(empty) py 0 R 0 0 shapes ok
15 of 19 agree
8 Four words, two languages
None of this is a package yet, and the distinction matters more here than anywhere else in the book. There are now three implementations of these four words and not one of them ships: the Python prototypes in design/, a hand-written R re-implementation, and the Rust core. What is missing is the thin R and Python packages that would call the core — and until those exist, nobody can install any of it.
The three agree on every sentence in this chapter. That is a fact about the plumbing and not about the vocabulary, which is the distinction the end of this chapter is about.
8.1 rows — say what a row is, not where it lives
The hypothesis in one line: every existing tool makes you state paths, from which the row shape emerges as a side effect. rows makes you state what a row is.
rows(doc, "versions.*")rows(doc, "versions.*")* is “every key here, whatever it is called” — which is what makes it work on a document whose keys are data. The keys it matched come back beside the records, because on a keys-as-data document the key is the most important column and a tool that discards it has thrown away the version number.
8.2 first_present — a priority order, not a set
The first of these paths that is actually there.
first_present(node, "valueQuantity", "valueString", "valueCodeableConcept",
default = NULL)first_present(node, "valueQuantity", "valueString", "valueCodeableConcept",
default=None)Both halves of the name carry something people get wrong. first says the arguments are a priority order rather than a set. present says the only value skipped is a missing one — so a zero comes back.
This is the first word shared with the sibling project, where it is the same idea over a table rather than a document. Sharing a word across two projects needs a stated owner and a test on both sides from the day it is shared, or the two drift and the drift is invisible.
8.3 take — one row per record, one column per path
take(records, "name", "author.email", "dist.tarball")take(records, "name", "author.email", "dist.tarball")Nothing else is built, and that is the whole point. The measured cost claim is that building only the columns you asked for skips 97.9% of the cells a general-purpose flattener would materialise.
8.4 where — find the value, not the path
The verb for a document you have never seen: every path whose value matches, folded.
where(doc, "url")where(doc, "url")Folded, because otherwise it is the O(data) failure arriving through the front door — 5,511 matching paths in one corpus file, which is a wall of text rather than an answer. It reports the shapes instead.
8.5 The claim, checked
The two implementations were written independently and are diffed on real documents. This is the harness running now:
8.6 Why a second implementation was written at all
This looks like exactly the mistake the architecture forbids. One Rust core, so that two hand-written copies can never drift — and here are two hand-written copies.
The distinction is that one of them is a probe rather than a product, and it answers a question the core cannot:
One core makes the two languages agree by construction. That proves the plumbing. It cannot tell you whether the vocabulary is right. If
rows("versions.*")reads naturally in Python and awkwardly in R, a shared core delivers the awkward reading to R users faithfully and forever. The port does not test that assumption, it locks it in.
The only way to test it is to have the words re-derived from the written notation by another route, and see whether they land in the same place. They did, on every sentence above.
Two hand-written copies must never be shipped, because they drift invisibly. Writing one as a probe and throwing it away costs nothing and buys the one piece of evidence the architecture assumes.
8.6.1 The core now answers these sentences, and the R copy has not been deleted
The plan said design/fathom.R goes the day the core answers them. It does — rows and where in Rust land on the same figures as both the Python and the R, on all nineteen.
It is kept anyway, and the reason is worth more than the rule. The same plan keeps the parity harness by retargeting it from two implementations to two bindings of one core. There are no bindings yet. Deleting the R today would break that harness and leave the core checked against one implementation where it is currently checked against two — trading a working check for nothing, to be tidy.
It goes when the R package exists to replace it. Written down as a deliberate deferral, because a plan followed to the letter at the cost of the thing it was protecting is not being followed at all.