You can write a "meta-macro" helper to derive a macro that munches sequences out of a set of rules for the singular case.
Showcase
macro_enhance! { // <- meta-macro helper
#[macro_enhance::with_separator( , )]
#[macro_enhance::join_with {
(
$( // repetition over all the expansions
$($expansion:tt)* // a single expansion
)*
) => (
$(
$($expansion)* ;
)*
);
}]
// single expansions rules
macro_rules! x_or_y {
(
X
) => (
println!("X")
);
(
Y
) => (
println!("Y")
);
}
}
fn main ()
{
x_or_y!(X, Y, X, X, Y);
}
which expands to:
fn main ()
{
println!("X");
println!("Y");
println!("X");
println!("X");
println!("Y");
}
-
Playground (feel free to click on "expand macros" on the right)
Regarding your matches_ch!
macro, I think there is a clear case of XY here: you should explain what you are trying to accomplish, and really think if using such a complex macro is worth the very little gain it yields.
That is, from looking at your macro, if I've guessed it right (I may very well have not!), you want to be able to support the following:
match_ch!( (NonZeroU8::new(x) {
Some(42) => { ... },
Some(x) if x % 2 == 0 => { ... },
// etc.
SPECIAL_END_BRANCHES_HERE
})
where your SPECIAL_END_BRANCHES_HERE
are expected to be:
$( None => { ... }, )?
some_var_name => { ... }, // or _ => ...
And depending on whether the literal None
branch was provided or not, some_var_name
would bind to an Option<NonZeroU8>
equal to Some(x)
if None
was provided, or None
if not.
In case I've guessed it right
I personally find the syntax confusing, especially given that:
-
the compiler is already smart enough to know that after it has checked for a None
branch, it can skip null-checking on the following Some(some_var_name)
branch;
-
If you want to have None
be bound to some_var_name
, you can use the some_var_name @ None
pattern.
So, instead of:
match_ch!( (NonZeroU8::new(x)) {
Some(42) => { ... },
Some(x) if x % 2 == 0 => { ... },
None => { ... },
foo => { ... },
})
you could write:
match NonZeroU8::new(x) {
Some(42) => { ... },
Some(x) if x % 2 == 0 => { ... },
None => { ... },
foo @ Some(_) => { ... },
/* or better:
Some(foo) => { ... }, // */
}
and instead of:
match_ch!( (NonZeroU8::new(x)) {
Some(42) => { ... },
Some(x) => { ... },
foo => { ... },
})
you could write:
match NonZeroU8::new(x) {
Some(42) => { ... },
Some(x) => { ... },
foo @ None => { ... },
}