Skip to content

Bare flag sugar#18

Merged
jw3126 merged 1 commit into
jw3126:masterfrom
PatrickHaecker:bare-flag-sugar
May 14, 2026
Merged

Bare flag sugar#18
jw3126 merged 1 commit into
jw3126:masterfrom
PatrickHaecker:bare-flag-sugar

Conversation

@PatrickHaecker

Copy link
Copy Markdown

Allow using @batteries T kwshow instead of @batteries T kwshow=true. This is nice on its own, but also used in a later PR.
This builds on #17, so its diff will be smaller after #17 is merged.

@jw3126

jw3126 commented May 6, 2026

Copy link
Copy Markdown
Owner

Thanks for the PR! Can you pitch the advantages of this syntactic sugar? The pro I see is slightly more concise @batteries calls?
Drawback would be slightly more complexity and another syntax for readers to be aware of. It is in contrast to what e.g. f(;kwshow) would do.

@PatrickHaecker

PatrickHaecker commented May 7, 2026

Copy link
Copy Markdown
Author

Thanks for having a look on this PR (and merging #17).

Can you pitch the advantages of this syntactic sugar? The pro I see is slightly more concise @Batteries calls?

Yes, it's nice that the calls are a bit more concise improving the signal-to-noise ratio. However, the real reason to have this is #19:

@batteries can be problematic when you only want to define a single method or only a certain selection of methods. You would need to explicitly opt-out from every method active by default. However, which methods are active by default can change. So whenever you update StructHelpers.jl and the defaults change, you'd need to think through all your usages of @batteries and therefore the affected types to see whether the changed definition is still valid for your whole program. No problem for smaller programs, but quite a burden for larger ones. So the focus of @batteries seems to be on rapid development and REPL usage, which is totally fine.

However, for large programs, the explicit @battery is probably the better choice. However, when listing the to-be-defined methods there, it's quite tedious (and less readable) to append each method name with =true. On the other hand we want to reduce code duplication and we want to keep the user interface as simple, and therefore as consistent, as possible.

That's why both @battery and @batteries should support the keyval and the bare flag syntax to share the same code paths and provide a unified user interface. So #18 is preparatory for #19. I split it up because it's both a different functionality and it makes the review hopefully easier.

Sorry for only vaguely hinting at a "future PR", but the @battery PR just has not been ready yet. I hope I could clarify it now.

@PatrickHaecker

PatrickHaecker commented May 7, 2026

Copy link
Copy Markdown
Author

A bare symbol is now accepted as shorthand for \`flag=true\`:

    @Batteries T kwconstructor   # equivalent to kwconstructor=true
    @Batteries T kwconstructor kwshow hash=false   # mixable

Also unblocks the cleaner subset-mode call shape we want for an
upcoming \`@battery\` macro that derives a single hand-picked battery.
PatrickHaecker pushed a commit to PatrickHaecker/StructHelpers.jl that referenced this pull request May 14, 2026
Closes jw3126#12.

This is the real PR I wanted to do. All the others are basically there
to enable this one.

Introduces a new `@batteries` / `@battery` flag `showrepr=true` that
overloads `Base.show` to print a heuristically short constructor call
which round-trips through `eval`, as an alternative to the existing
`kwshow`. The two are mutually exclusive (both target `Base.show`).

I originally wanted to just extend `kwshow`. However, as the
redundancy reduction should also be available if there is no keyword
constructor and/or calls are short when using a parametric
constructor, this would have lead to broken backwards-compatibility
requiring a major version bump and user changes. But as both
approaches have different advantages, it's probably a good thing
to have both in the future.

Highlights:

* Probes every constructor of the type — positional, keyword, and
  hybrid (including the pair synthesized by `Base.@kwdef`) — and picks
  the shortest call whose result is `repr_eq` to the original. Trailing
  fields whose values match a default are omitted.
* Per-field literal shortening where the constructor still accepts the
  substitute: `0x000000000000002a` → `42`, whole-valued floats drop the
  `.0` suffix, `2//1` → `2`, `2 + 0im` → `2`.
* Uniform / run-length-compressed vectors render as `fill(v, n)` (or
  `[v for _=1:n]` for non-`isbits` elements, to avoid aliasing on
  re-eval); heterogeneous vectors get per-run RLE only when it actually
  shortens the literal.
* Round-trip safety is the gating criterion throughout: every
  substitution is verified by reconstructing through the constructor
  and comparing via `repr_eq` (which accepts both `==` and `isequal` to
  handle `NaN`, `-0.0`, and custom equality).
* Falls back to a non-executable `T(field = value, …)` rendering when
  no constructor recreates the object.

`kwshow` keeps its existing fixed `T(f1 = v1, …)` shape and stability
guarantees; `showrepr`'s output is heuristic and not pinned across
minor releases. The README contrasts the two.

This builds on jw3126#18 and jw3126#19 which should be merged first.

Co-authored-by: Copilot <copilot@github.com>
@jw3126
jw3126 merged commit a500064 into jw3126:master May 14, 2026
4 checks passed
PatrickHaecker pushed a commit to PatrickHaecker/StructHelpers.jl that referenced this pull request May 15, 2026
Closes jw3126#12.

This is the real PR I wanted to do. All the others are basically there
to enable this one.

Introduces a new `@batteries` / `@battery` flag `showrepr=true` that
overloads `Base.show` to print a heuristically short constructor call
which round-trips through `eval`, as an alternative to the existing
`kwshow`. The two are mutually exclusive (both target `Base.show`).

I originally wanted to just extend `kwshow`. However, as the
redundancy reduction should also be available if there is no keyword
constructor and/or calls are short when using a parametric
constructor, this would have lead to broken backwards-compatibility
requiring a major version bump and user changes. But as both
approaches have different advantages, it's probably a good thing
to have both in the future.

Highlights:

* Probes every constructor of the type — positional, keyword, and
  hybrid (including the pair synthesized by `Base.@kwdef`) — and picks
  the shortest call whose result is `repr_eq` to the original. Trailing
  fields whose values match a default are omitted.
* Per-field literal shortening where the constructor still accepts the
  substitute: `0x000000000000002a` → `42`, whole-valued floats drop the
  `.0` suffix, `2//1` → `2`, `2 + 0im` → `2`.
* Uniform / run-length-compressed vectors render as `fill(v, n)` (or
  `[v for _=1:n]` for non-`isbits` elements, to avoid aliasing on
  re-eval); heterogeneous vectors get per-run RLE only when it actually
  shortens the literal.
* Round-trip safety is the gating criterion throughout: every
  substitution is verified by reconstructing through the constructor
  and comparing via `repr_eq` (which accepts both `==` and `isequal` to
  handle `NaN`, `-0.0`, and custom equality).
* Falls back to a non-executable `T(field = value, …)` rendering when
  no constructor recreates the object.

`kwshow` keeps its existing fixed `T(f1 = v1, …)` shape and stability
guarantees; `showrepr`'s output is heuristic and not pinned across
minor releases. The README contrasts the two.

This builds on jw3126#18 and jw3126#19 which should be merged first.

Co-authored-by: Copilot <copilot@github.com>
PatrickHaecker pushed a commit to PatrickHaecker/StructHelpers.jl that referenced this pull request May 17, 2026
Closes jw3126#12.

This is the real PR I wanted to do. All the others are basically there
to enable this one.

Introduces a new `@batteries` / `@battery` flag `showrepr=true` that
overloads `Base.show` to print a heuristically short constructor call
which round-trips through `eval`, as an alternative to the existing
`kwshow`. The two are mutually exclusive (both target `Base.show`).

I originally wanted to just extend `kwshow`. However, as the
redundancy reduction should also be available if there is no keyword
constructor and/or calls are short when using a parametric
constructor, this would have lead to broken backwards-compatibility
requiring a major version bump and user changes. But as both
approaches have different advantages, it's probably a good thing
to have both in the future.

Highlights:

* Probes every constructor of the type — positional, keyword, and
  hybrid (including the pair synthesized by `Base.@kwdef`) — and picks
  the shortest call whose result is `repr_eq` to the original. Trailing
  fields whose values match a default are omitted.
* Per-field literal shortening where the constructor still accepts the
  substitute: `0x000000000000002a` → `42`, whole-valued floats drop the
  `.0` suffix, `2//1` → `2`, `2 + 0im` → `2`.
* Uniform / run-length-compressed vectors render as `fill(v, n)` (or
  `[v for _=1:n]` for non-`isbits` elements, to avoid aliasing on
  re-eval); heterogeneous vectors get per-run RLE only when it actually
  shortens the literal.
* Round-trip safety is the gating criterion throughout: every
  substitution is verified by reconstructing through the constructor
  and comparing via `repr_eq` (which accepts both `==` and `isequal` to
  handle `NaN`, `-0.0`, and custom equality).
* Falls back to a non-executable `T(field = value, …)` rendering when
  no constructor recreates the object.

`kwshow` keeps its existing fixed `T(f1 = v1, …)` shape and stability
guarantees; `showrepr`'s output is heuristic and not pinned across
minor releases. The README contrasts the two.

This builds on jw3126#18 and jw3126#19 which should be merged first.

Co-authored-by: Copilot <copilot@github.com>
PatrickHaecker pushed a commit to PatrickHaecker/StructHelpers.jl that referenced this pull request May 18, 2026
Closes jw3126#12.

This is the real PR I wanted to do. All the others are basically there
to enable this one.

Introduces a new `@batteries` / `@battery` flag `showrepr=true` that
overloads `Base.show` to print a heuristically short constructor call
which round-trips through `eval`, as an alternative to the existing
`kwshow`. The two are mutually exclusive (both target `Base.show`).

I originally wanted to just extend `kwshow`. However, as the
redundancy reduction should also be available if there is no keyword
constructor and/or calls are short when using a parametric
constructor, this would have lead to broken backwards-compatibility
requiring a major version bump and user changes. But as both
approaches have different advantages, it's probably a good thing
to have both in the future.

Highlights:

* Probes every constructor of the type — positional, keyword, and
  hybrid (including the pair synthesized by `Base.@kwdef`) — and picks
  the shortest call whose result is `repr_eq` to the original. Trailing
  fields whose values match a default are omitted.
* Per-field literal shortening where the constructor still accepts the
  substitute: `0x000000000000002a` → `42`, whole-valued floats drop the
  `.0` suffix, `2//1` → `2`, `2 + 0im` → `2`.
* Uniform / run-length-compressed vectors render as `fill(v, n)` (or
  `[v for _=1:n]` for non-`isbits` elements, to avoid aliasing on
  re-eval); heterogeneous vectors get per-run RLE only when it actually
  shortens the literal.
* Round-trip safety is the gating criterion throughout: every
  substitution is verified by reconstructing through the constructor
  and comparing via `repr_eq` (which accepts both `==` and `isequal` to
  handle `NaN`, `-0.0`, and custom equality).
* Falls back to a non-executable `T(field = value, …)` rendering when
  no constructor recreates the object.

`kwshow` keeps its existing fixed `T(f1 = v1, …)` shape and stability
guarantees; `showrepr`'s output is heuristic and not pinned across
minor releases. The README contrasts the two.

This builds on jw3126#18 and jw3126#19 which should be merged first.

Co-authored-by: Copilot <copilot@github.com>
@PatrickHaecker
PatrickHaecker deleted the bare-flag-sugar branch May 19, 2026 06:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants