It's a somewhat repeated desire to be able to expand macro code if a $()?
captured anything but without actually capturing/expanding any matchers for the contents of the repetition. An oft proposed solution is some kind of $:empty
matcher which could be inserted into the macro which both captures and expands to nothing, serving only to mark which repetitions to expand.
I just stumbled into a silly way to do this that works today. Specifically, I wrote a macro
macro_rules! impl_vector {{
$(use Guest $(as $Guest:ident)?;)?
$(const $N:ident: usize;)?
type $Vector:ident;
$($items:item)*
} => {
const _: () = {
$(const $N: usize = 2;)?
$(use crate::ffi::vec2f::Guest $(as $Guest)?;)?
type $Vector<T> = Vector2<T>;
$($items)*
};
const _: () = {
$(const $N: usize = 3;)?
$(use crate::ffi::vec3f::Guest $(as $Guest)?;)?
type $Vector<T> = Vector3<T>;
$($items)*
};
}}
Note specifically the $($(as $Guest)?)?
. In an invocation that only writes use Guest;
, the expansion expands the outer $()?
but not the inner $()?
; the inner $()?
only really serves to determine what repetition the outer $()?
pairs to, because I don't have any invocations which do use Guest as Alias;
instead.
So the pattern is: if you find yourself wanting to capture $x:empty
in a macro_rules!
pattern, you can write something like $( __nobody_will_ever_use_this_identifier_i_hope $x:tt )?
instead, "expanding" it to nothing with $($x)?
. This will only cause errors if someone invokes your macro with the token __nobody_will_ever_use_this_identifier_i_hope
whever your :empty
shim matches.