TL;DR: Should we have some way to reference repetitions themselves at code substitution, without needing their inner fragment metavars?
If one defines repetition in macro-by-example like $(foo)?
, he won't be able to perform macro substitution based on that repetition - because it doesn't have captures. However such scenario allows using flag-like keywords in macros without needing to resorting to proc-macros, or just substituting fragment without using any of its captures.
The closest thing I found is macro metavar RFC, although it wasn't implemented and doesn't cover repetition fragments without captures.
I see two options here:
-
Dummy fragment
$frag:dummy
(metavar type here just for illustration) which always captures empty set of tokens and expands into empty set of tokens. As a result,$(keyword $kwd:dummy)?
would matchkeyword
optional repetition and expand it using$(code for keyword $kwd)?
. I've seen some attempts to discuss this variant here and there, though can't find links now.Pros:
- doesn't need special syntax
Cons:
- fragment capture may look nontrivial
- possible issues with parser
-
Give labels to repetitions themselves. Something like
$'rep:(keyword)?
expanded using$'rep:()
. Haven't seen this variant proposed.Pros:
- clearly references repetition itself without ambiguity
- shouldn't influence sources parser, as it just gives name to existing macro entity
Cons
- requires new syntax which may not fit normal declaration
$var:metatype
vs substitution$var
pattern
Use cases
My personal use-case was a macro which defines certain struct with a subset of fields from a fixed full set. It indeed could've been done using Option
, but I had to optimize code size, and normal reference implementation (which used those options) bloated crazily because it had to match all combinations of fields presence to serialize just the needed subset. I wanted to create macro with matcher like $struct_name:ident { $(field_0)? $(field_1)? $(field_2)? }
which would generate specific subset of the struct in question based on fields mentioned. Alas, it requires proc macros ATM, so I resorted to manual boilerplate.