Chapter 14 — 14-atoms-text — is built and CI-green. #15

Merged
navicore merged 3 commits from chapter14 into main 2026-06-26 01:51:53 +00:00
Owner

What landed

Five exercises, each giving its builtin a real job (not a mechanism demo), covering the whole design-doc roster (atom_length, atom_concat, atom_chars, number_chars, number_codes):

┌─────┬──────────────────┬─────────────────────┬────────────────────────────────────────────────────────────┐
│ # │ File │ Builtin │ The job │
├─────┼──────────────────┼─────────────────────┼────────────────────────────────────────────────────────────┤
│ 01 │ 01-measure │ atom_length/2 │ total_length/2 — sum the lengths of a list of atoms (the │
│ │ │ │ ch06 sum-a-list shape, now measuring first) │
├─────┼──────────────────┼─────────────────────┼────────────────────────────────────────────────────────────┤
│ 02 │ 02-join │ atom_concat/3 │ qualify/3 — join Module:Name, teaching that a separator is │
│ │ │ (forward) │ just another atom joined in its own step │
├─────┼──────────────────┼─────────────────────┼────────────────────────────────────────────────────────────┤
│ │ │ atom_concat/3 │ starts_with/2 + ends_with/2 — the relational "aha" (the │
│ 03 │ 03-prefix-suffix │ (split) │ append/3-style multi-mode the design doc flags from issue │
│ │ │ │ #35) │
├─────┼──────────────────┼─────────────────────┼────────────────────────────────────────────────────────────┤
│ 04 │ 04-spell │ atom_chars/2 (both │ reverse_atom/2 — bridge atom↔list, reusing reverse/2 from │
│ │ │ ways) │ ch10 │
├─────┼──────────────────┼─────────────────────┼────────────────────────────────────────────────────────────┤
│ │ │ number_chars/2 + │ sum a number's digits two ways, contrasting char-atoms │
│ 05 │ 05-digit-sum │ number_codes/2 │ (convert back) vs integer-codes (subtract 48) — a callback │
│ │ │ │ to ch13's arithmetic digit_sum │
└─────┴──────────────────┴─────────────────────┴────────────────────────────────────────────────────────────┘

Every building block was probe-verified against installed plgc 0.3.2 before authoring (per the established workflow); no new upstream defects surfaced. Registered in info.toml, and the curriculum tables in README.md and docs/ROADMAP.md (67→72) updated.

Two things worth noting:

  • I renamed the split exercise to 03-prefix-suffix because 03-split already exists in ch10 and exercise names are globally unique in the registry.
  • After your feedback, I reworked all five hints so they describe what each goal accomplishes rather than handing over the literal clause — base cases especially (e.g. "there are no atoms to measure, so the total can only be one thing" instead of total_length([], 0)). I saved that balance as durable guidance for the remaining chapters.

just ci: fmt + clippy clean, all 72 exercises validated (each solution passes, each starter parses).

What landed Five exercises, each giving its builtin a real job (not a mechanism demo), covering the whole design-doc roster (atom_length, atom_concat, atom_chars, number_chars, number_codes): ┌─────┬──────────────────┬─────────────────────┬────────────────────────────────────────────────────────────┐ │ # │ File │ Builtin │ The job │ ├─────┼──────────────────┼─────────────────────┼────────────────────────────────────────────────────────────┤ │ 01 │ 01-measure │ atom_length/2 │ total_length/2 — sum the lengths of a list of atoms (the │ │ │ │ │ ch06 sum-a-list shape, now measuring first) │ ├─────┼──────────────────┼─────────────────────┼────────────────────────────────────────────────────────────┤ │ 02 │ 02-join │ atom_concat/3 │ qualify/3 — join Module:Name, teaching that a separator is │ │ │ │ (forward) │ just another atom joined in its own step │ ├─────┼──────────────────┼─────────────────────┼────────────────────────────────────────────────────────────┤ │ │ │ atom_concat/3 │ starts_with/2 + ends_with/2 — the relational "aha" (the │ │ 03 │ 03-prefix-suffix │ (split) │ append/3-style multi-mode the design doc flags from issue │ │ │ │ │ #35) │ ├─────┼──────────────────┼─────────────────────┼────────────────────────────────────────────────────────────┤ │ 04 │ 04-spell │ atom_chars/2 (both │ reverse_atom/2 — bridge atom↔list, reusing reverse/2 from │ │ │ │ ways) │ ch10 │ ├─────┼──────────────────┼─────────────────────┼────────────────────────────────────────────────────────────┤ │ │ │ number_chars/2 + │ sum a number's digits two ways, contrasting char-atoms │ │ 05 │ 05-digit-sum │ number_codes/2 │ (convert back) vs integer-codes (subtract 48) — a callback │ │ │ │ │ to ch13's arithmetic digit_sum │ └─────┴──────────────────┴─────────────────────┴────────────────────────────────────────────────────────────┘ Every building block was probe-verified against installed plgc 0.3.2 before authoring (per the established workflow); no new upstream defects surfaced. Registered in info.toml, and the curriculum tables in README.md and docs/ROADMAP.md (67→72) updated. Two things worth noting: - I renamed the split exercise to 03-prefix-suffix because 03-split already exists in ch10 and exercise names are globally unique in the registry. - After your feedback, I reworked all five hints so they describe what each goal accomplishes rather than handing over the literal clause — base cases especially (e.g. "there are no atoms to measure, so the total can only be one thing" instead of total_length([], 0)). I saved that balance as durable guidance for the remaining chapters. just ci: fmt + clippy clean, all 72 exercises validated (each solution passes, each starter parses).
Chapter 14 — 14-atoms-text — is built and CI-green.
All checks were successful
CI - Linux / CI - Linux x86_64 (pull_request) Successful in 45s
49cd765f2d
What landed

Five exercises, each giving its builtin a real job (not a mechanism demo), covering the whole design-doc roster (atom_length, atom_concat, atom_chars, number_chars, number_codes):

┌─────┬──────────────────┬─────────────────────┬────────────────────────────────────────────────────────────┐
│  #  │       File       │       Builtin       │                          The job                           │
├─────┼──────────────────┼─────────────────────┼────────────────────────────────────────────────────────────┤
│ 01  │ 01-measure       │ atom_length/2       │ total_length/2 — sum the lengths of a list of atoms (the   │
│     │                  │                     │ ch06 sum-a-list shape, now measuring first)                │
├─────┼──────────────────┼─────────────────────┼────────────────────────────────────────────────────────────┤
│ 02  │ 02-join          │ atom_concat/3       │ qualify/3 — join Module:Name, teaching that a separator is │
│     │                  │ (forward)           │  just another atom joined in its own step                  │
├─────┼──────────────────┼─────────────────────┼────────────────────────────────────────────────────────────┤
│     │                  │ atom_concat/3       │ starts_with/2 + ends_with/2 — the relational "aha" (the    │
│ 03  │ 03-prefix-suffix │ (split)             │ append/3-style multi-mode the design doc flags from issue  │
│     │                  │                     │ #35)                                                       │
├─────┼──────────────────┼─────────────────────┼────────────────────────────────────────────────────────────┤
│ 04  │ 04-spell         │ atom_chars/2 (both  │ reverse_atom/2 — bridge atom↔list, reusing reverse/2 from  │
│     │                  │ ways)               │ ch10                                                       │
├─────┼──────────────────┼─────────────────────┼────────────────────────────────────────────────────────────┤
│     │                  │ number_chars/2 +    │ sum a number's digits two ways, contrasting char-atoms     │
│ 05  │ 05-digit-sum     │ number_codes/2      │ (convert back) vs integer-codes (subtract 48) — a callback │
│     │                  │                     │  to ch13's arithmetic digit_sum                            │
└─────┴──────────────────┴─────────────────────┴────────────────────────────────────────────────────────────┘

Every building block was probe-verified against installed plgc 0.3.2 before authoring (per the established workflow); no new upstream defects surfaced. Registered in info.toml, and the curriculum tables in README.md and docs/ROADMAP.md (67→72) updated.

Two things worth noting:
- I renamed the split exercise to 03-prefix-suffix because 03-split already exists in ch10 and exercise names are globally unique in the registry.
- After your feedback, I reworked all five hints so they describe what each goal accomplishes rather than handing over the literal clause — base cases especially (e.g. "there are no atoms to measure, so the total can only be one thing" instead of total_length([], 0)). I saved that balance as durable guidance for the remaining chapters.

just ci: fmt + clippy clean, all 72 exercises validated (each solution passes, each starter parses).
Done. The seed in ch01 05-arith-in-rule, right after the double/2 example:
All checks were successful
CI - Linux / CI - Linux x86_64 (pull_request) Successful in 45s
123e451261
▎ Worth filing away for later: is/2 evaluates its right-hand side the moment the goal runs, so everything on that side must already be known. Here that's automatic — N arrives as an input. But once a rule body has several goals, it means the goal that computes a value has to come BEFORE the goal that uses it.

It states the rule the first time is/2 appears in a rule, but flags it as a for-later note ("once a rule body has several goals") since this exercise is still single-goal — so it plants the idea without overloading an intro exercise. By the time the learner hits ch14 01-measure and writes their first multi-goal accumulator, the full callout reads as "ah, that's what that note meant" rather than a cold surprise.

Comment-only, starter still parses (exit 1), nothing else touched.
● Green. Chapter 14 is now 6 exercises, and the contrived twin is gone.
All checks were successful
CI - Linux / CI - Linux x86_64 (pull_request) Successful in 1m1s
1acb81e00e
What changed:

  - ex 5 → 05-count-digit (new) — number_chars. Task: count_digit(2020, '0', N) → N = 2. You spell the number into
  char atoms and a recursive helper counts matches with ==/\==. It wants the char face precisely because you're
  comparing characters, not computing on them.
  - ex 6 → 06-digit-sum (was the twin, now codes-only) — number_codes. The ch13 digit-sum reprise: each digit is
  Code - 48, plain arithmetic. It wants the code face because you're computing.

  The chars/codes distinction is now earned by the tasks — different signatures, different answers, different
  reasons to reach for each — instead of asserted by running the same I/O through both builtins. And both share
  the walk-a-list recursive skeleton from ex 01, so the helper structure shows up as a reused shape across two
  genuinely different problems, with each exercise's prose carrying only one builtin. ex 6's prose and hint
  explicitly call back to ex 5 ("last exercise you compared; here you compute").

  Arc now reads: ex4 atom_chars → ex5 number_chars (chars family, adjacent) → ex6 number_codes digit-sum as the
  finale and ch13 callback. Registry, ROADMAP (73), and README tables all updated; just ci is clean — all 73
  validated against plgc.
navicore deleted branch chapter14 2026-06-26 01:51:53 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
navicore/loglings!15
No description provided.