Skip to content

feat(language): a sum through a relation names its columns after a dot - #603

Closed
FBumann wants to merge 2 commits into
mainfrom
claude/math-spec-pr-509-semantics-ari3bb
Closed

FBumann wants to merge 2 commits into
mainfrom
claude/math-spec-pr-509-semantics-ari3bb

Conversation

@FBumann

@FBumann FBumann commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Prompt: Let's do a new branch, rebasing this onto current main

Note

The following content was generated by AI.

What this changes

A sum through a relation names its columns after a dot: sum(x, over=l.a) reads from column a, and sum(x, by=l.b) lands on b. shift, sum_back and position take a dotted along=. at is unchanged.

retired now
sum(x, by=l, over=a, into=b) sum(x, over=l.a)
sum(x, by=l, over=[a, b], into=[c, d]) sum(x, by=l.[c, d])
shift(x, along=d, by=l, within=c) shift(x, along=l.a, within=c)
sum_back(x, along=d, by=l, within=c) sum_back(x, along=l.a, within=c)
position(d, by=l, within=c) position(l.a, within=c)

This is a break with no alias. The retired spellings are refused by the call
shape, with the signature quoted back. Every example, fixture and page moves in
this PR.

over= names the columns the sum reads from and the relation supplies the other
end: the one value column left over is what it lands on, and the key columns it
does not name are joined on. by= names the landing set and the rest of the key
is summed away. A key column named beside a value column is joined on; where
only key columns are named, they are what the sum lands on, which is how a bare
relation is still summed.

Why

This is the design of #509, ported onto current main rather than rebased:
main has since renamed Walk to Direction (#494), made Partition a class
of its own (#559) and dropped relation lists (#533), so the old branch's diff no
longer applies. #509 stays closed and its branches are untouched.

The review on #509 asked for two changes, and both are here. x[rel] indexing
is left out, so at keeps its spelling and the surface to argue about is
smaller. over= no longer lands on every value column silently: where more than
one is left over it is refused, naming the by= that says which.

Scope, evidence, gates and what was left out

Scope the user chose

  • Port the design rather than replay the commits.
  • Dot only, defer x[rel].
  • by= admits key columns, so the landing set can be named exactly.

New refusals, each with a test

  • over= leaves several value columns, or none — the over-capture the review
    found (technology riding along); the message names the by= rewrite.
  • by= lands twice on one dimension (by=ends.[bus0, bus1]).
  • by= sums two key columns over one dimension away.
  • within= beside a bare-dimension along=.
  • A relation named without its column, in over=, along= or by=.
  • A dotted name in a value position.
  • A macro formal standing before the dot now substitutes, where over=r.g
    raised KeyError: 'r' on feat(language): a relation is summed with over=/by= and indexed with x[rel] #509.

One guard deleted

_check_joined's "two joined columns over one dimension" is unreachable under
the dot form: joined is only ever the key columns of a valued relation, and
the declaration already refuses two of those over one dimension. Its sibling —
a joined column that is also consumed — stays, and
tests/test_dimensions.py::test_a_joined_column_is_not_also_consumed covers it.
The row that reached the deleted branch,
a-call-joining-one-dimension-through-two-columns, is gone with it.

Guard table

Each new guard disabled in turn, tests/test_validation.py,
test_dimensions.py, test_expansion.py and test_lowering.py run:

guard result
over= two columns over one dimension caught
over= leaves no value column caught
over= leaves several value columns caught
by= sums nothing away caught
by= lands twice on one dimension caught
by= sums two columns over one dimension away caught
within= on a bare dimension caught
a relation named without its column caught
by= without a column caught
a partition steps along one key column caught
a partition names its group caught
within= names a key column caught
a joined column is also consumed caught

Gates

  • pytest — 1376 passed, 6 skipped.
  • ruff check and ruff format --check — clean.
  • pyrefly check — the same findings as main, less two the change removes.
  • mkdocs build — clean. --strict aborts on the sandbox's blocked fetch of
    https://docs.python.org/3/objects.inv, which is the network and not the
    pages.
  • compile-tex was not run: this sandbox has no TeX toolchain.
  • Generated files regenerated, not edited: the schema, the gallery, the
    notation page, the operator page and the golden output. The golden .out
    files came back byte for byte, because the math is the same.

Deliberately not done

Departures from AGENTS.md

  • No pixi in this sandbox, so the gates ran in a uv virtualenv on Python
    3.13 with the dependencies installed from PyPI.
  • The branch lives in the primary checkout rather than a ../wt/ worktree.

Generated by Claude Code

@FBumann FBumann added the area: relations relations and dimensions: the relation design label Sep 22, 2026
@FBumann

FBumann commented Sep 23, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #641

@FBumann FBumann closed this Sep 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: relations relations and dimensions: the relation design

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants