Skip to content

a predicate cannot be read at the previous coordinate, so the start of a run cannot be named #591

Description

@FBumann

Prompt: "I want to be able to express all of them in assumptions. Are you sure we can't get curved working? Maybe we do t need all of it? We need this feature for 582" — "Do an issue for count and shift"

Note

The following content was generated by AI.

shift takes arithmetic, so a mask cannot be read one coordinate back. Without that, "admitted here and not admitted before" — the start of a run — cannot be written, and the points: contiguity condition stays a program class that #582 cannot emit.

What can be improved?

Shifting a predicate fails at the parser, because an operator argument is arithmetic and nothing else:

points AND NOT shift(points, along=bp, offset=1, edge=0)
  → Failed to parse where string

The proposal is to admit a predicate as shift's operand, where it yields a predicate:

shift(<predicate>, along=<dim>, offset=<n>[, by=<relation>, within=<column>])

No edge=, and that is the point

Arithmetic shift requires an edge= because the vacated position has no value and the loader refuses to invent one:

shift() over a variable-free expression leaves vacated positions with no value, and inventing one is what silently pinned a …

A predicate has a neutral value there, and the language already uses it: a missing row reads as false in every where. So a translated predicate is false at the vacated position, no keyword needed, nothing invented. This is the one place where the predicate vocabulary is simpler than the arithmetic one rather than poorer.

What it unlocks

With #590 for the count, Contiguous becomes an ordinary assumption — the marked breakpoints are one run when exactly one of them has no marked neighbour before it:

points: "count(points AND NOT shift(points, along=bp, offset=1), over=bp) == 1"

That is the condition #582's checklist singles out as the one that does not map today. Outside piecewise:, "it was off and now it is on" is an ordinary thing to mask on, and cannot be said now.

Admissibility

Pointwise. The operand keeps its own dimensions, no join is introduced, and a where carries no variables, so the degree rules are untouched. The typesetter already prints a translated index for arithmetic, and the same notation reads correctly for a predicate.

What is open

Any predicate, or only a leaf. shift(points, …) shifts a declared bool parameter. shift(p_max > 0, …) shifts a comparison. The second is the general rule and costs nothing extra to state, but the first is the whole of the known demand — worth deciding rather than discovering.

Whether by=/within= and edge='wrap' come along. A partitioned translation and a cyclic one are meaningful for a predicate too. The conservative landing is along= and offset= only, with the rest refused until a caller needs it.

Whether this is shift or a second name. One builtin that takes either vocabulary and returns what it was given is fewer concepts. A separate spelling keeps BUILTINS rows single-typed. The first is what the operator table implies; the second is what the resolver would find easier.

Order

#590 first — it stands alone and unlocks three of the four conditions. This one is only needed for the fourth, and its own use is the run start. Both are needed before #582 can emit a curve's conditions as assumptions: and retire Check, check_message and PiecewiseDeclaration.checks.

Version

v0.0.0-alpha.108

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: operatorsWhat an operator may reduce, walk, read or refusedesign: openIn scope; the spelling is undecided

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions