Skip to content

Should a particle that joins nothing still count as a particle? (Jong van der and Jong, van der already disagree) #404

Description

@derek73

A particle earns its name by joining forward to the word it modifies. When there is no such word, it is doing no particle work — and the parser already treats that two different ways depending on a comma:

Jong, van der   ->  given='van'   middle='der'   family='Jong'      initials='v. J.'
Jong van der    ->  given='Jong'  middle=''      family='van der'   initials='J.'

Same two words, same absence of anything to join. After a comma they are ordinary name words that take roles and initials; without one they stay a particle run, produce an empty family_base, and contribute no initials.

The proposed principle: not joining = not a particle. A particle run with no name word to attach to does not chain, so its words stay separate pieces and are positioned like any other name words. Jong van der would read given='Jong', middle='van', family='der' — matching what the comma form already does.

What it resolves

#385 directly. Seven of the 751 corpus names have a family that is all particles and therefore an empty family_base, so the surname vanishes from the initials:

                     today                                      proposed
Anh Do          family='Do'      base=''  initials='A.'    base='Do'   initials='A. D.'
Yin Le          family='Le'      base=''  initials='Y.'    base='Le'   initials='Y. L.'
Sander van      family='van'     base=''  initials='S.'    base='van'  initials='S. V.'
Smith van der   family='van der' base=''  initials='S.'    middle='van', family='der',
                                                           initials='S. V. D.'

The last is the only place the two readings in question (1) below diverge — split into middle/family, or one part that simply gains a base. The initials come out the same either way.

The reason has nothing to do with which half of the vocabulary the word is in. A never-given particle is not "never a given name" absolutely — it is never a given name while it is doing a particle's work. When the name is not supplied in a format that lets it do that work, the word is just another piece of text and takes whatever role its position gives it. Do being never-given does not stop it being a given name if you put it in that spot.

The parser already concedes this in two places. rules.md#P1's own Accepted: note says a bare "de" stays the given name because there is nothing to fold into — the same argument, applied to one input. And the comma path applies it to Jong, van der wholesale. The proposal is to stop making it a special case.

#402, without changing R3. If a word only stays a particle when it actually joins, no name part can ever consist solely of particles — which is #402's invariant, reached from the other side. R3's rule stays literally true and unconditional: any particle still tagged in a part is by definition joined to something, so "particles contribute nothing" needs no qualifier and the Juan van der edge stops being an edge.

Part of #365. A trailing particle landing alone in the middle role under FAMILY_FIRST is the same shape.

R2's empty base. The Accepted: note reasoning that van der "has no borne name to anchor a base" becomes unnecessary rather than merely tolerated.

This is not a licence to delete P1's fold

The principle justifies the fold rather than undermining it, and the boundary is worth stating so nobody reads it the other way.

de Mesnil    family='de Mesnil'  base='Mesnil'    a name word follows -> particle work -> fold
de           given='de'                           nothing follows     -> text          -> no fold

P1's fold already fires exactly where a name word is available for the particle to attach to, and already declines where none is. The test is whether a name word is available to modify — forward for a leading or mid-name particle, backward across a family comma (P6) — not whether grouping happened to chain it. P4 says a leading particle chains nothing structurally, yet de Mesnil is plainly particle work; the fold is what expresses that.

So the principle changes the shapes where no such word exists, and leaves every shape where one does.

Where the judgement has to live

This is a grouping change, not a rendering one. The particle tag is vocabulary, assigned at classify time from the wordlist; whether the word joins anything is structure, decided at group time. Today the renderers and the initials code read only the tag, which is why Anh Do reports family_particles='Do' for a word that is plainly the surname.

mechanisms.md#PIECES and #UNIT-PARTITION are the relevant patterns: the tag says what a word is, the piece says what it is doing, and every consumer that cares about function should be reading the second.

What needs deciding

  1. Does a two-particle run split, or stay one part? Juan van der → middle='van', family='der' (the split reading, matching the comma form), or one part that simply gains a base?
  2. Does this reach the given role? van Gogh gives given='van' today and already initials, via an unstated carve-out at nameparser/_render.py:113 (if role is not Role.GIVEN). Under this principle that carve-out becomes a consequence of the rule rather than an exception to it, and can be deleted.
  3. Blast radius. This moves shipped default-order output, so it needs a differential pass and ledger rules at all three baselines. The corpus shapes above are the visible part; the change is broader than seven names.

Why it is worth the disruption

#385, #402 and the middle half of #365 are the same defect wearing different field names: a word the vocabulary calls a particle sitting alone in a name part, where the vocabulary's claim is not true of that occurrence. Fixing them one field at a time means three separate judgements about one question.

Activity

  1. self-assigned this
    on Aug 19, 2026
  2. derek73 commented on Aug 19, 2026

    @derek73
    OwnerAuthor

    Resolved in both halves by #406, which is merged.

    The rendering half is implemented. A name part whose every word is particle vocabulary is a part where none of them is doing a particle's work, so they read as ordinary name words — anchoring family_base, leaving family_particles, and contributing initials. rules.md#R2 was rewritten around it: the discriminator is position, not "borne as an ordinary surname somewhere", which would have needed all 70 particles adjudicated for a distinction the vocabulary does not record.

    The invariant that came out of it is the durable part, and is now asserted as a partition over the whole case table under all three name orders:

    A non-empty family always has a non-empty base. A particle needs a base to attach to.

    43 of 751 corpus names × 3 orders violated it; 0 do now.

    The grouping half is declined, with measurements, recorded under decisions.md#R2's Declined:. Grouping can decline to merge but cannot keep the words apart — roles re-assemble them, and two adjacent same-role pieces are one part at the field level. "Juan Smith van der" would become middle 'Smith van', family 'der': a base of der rather than van der, and a middle name nobody wrote. The split needs the leftover distribution to know these are separate units, which is mechanisms.md#UNIT-PARTITION's problem.

    Question 2 answered differently than the issue predicted. The issue said the _render.py GIVEN carve-out "becomes a consequence of the rule rather than an exception to it, and can be deleted". Measured: with the rule in place, removing the carve-out still changes 179 of 2,253 initials, because it covers a particle sitting alongside a name word in the given role (Alex van Johnson under FAMILY_FIRST). The two are independent and the carve-out is load-bearing.

    Three follow-ups the implementation surfaced, all filed: #405 (no ambiguity is reported for the fork P6 decides), #407 (capitalized() still lowercases these words), #408 (initials() ignores the folded-word ordering the family field applies).

    Closing. #385 and #402 closed with the PR.

  3. added this to the v2.2 milestone on Aug 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions