Reputation: 339
I am trying to match user-provided lists in a macro, but the repeat-pattern does not match the same branches depending on whether I call the macro on single items directly, or whether I call it from a repeat block.
Input code (playground link):
macro_rules! foo {
($a:ident) => { println!("Printing ident"); };
($b:literal) => { println!("Printing literal"); };
([ $($something:expr),+ $(,)? ]) => {
println!("Printing repeat");
$(
foo!($something);
)*
};
($catch_all:expr) => { println!("Printing expr"); };
}
fn main() {
foo!(baz);
foo!([1, "asd"]);
foo!([baz]);
}
Output:
Printing ident
Printing repeat
Printing literal
Printing literal
Printing repeat
Printing expr
The first line prints the "ident" line, the last one prints the "expr" line (the other one is just to show that what I want to do works, with literals, at least).
My problem with this behavior is that I also expect expr
from the user, and now I cannot distinguish raw ident from expr.
To be more specific, I would like to be able to write foo!(["a literal", some_ident, complex_stuff!()])
, where all three parameters are treated differently.
Upvotes: 0
Views: 229
Reputation: 27437
To avoid forcing the type of a token you can match with the type tt
:
macro_rules! foo {
($a:ident) => { println!("Printing ident"); };
($b:literal) => { println!("Printing literal"); };
([ $($something:tt),+ $(,)? ]) => {
println!("Printing repeat");
$(
foo!($something);
)*
};
($catch_all:expr) => { println!("Printing expr"); };
}
Results in the following with your main
.
Printing ident
Printing repeat
Printing literal
Printing literal
Printing repeat
Printing ident
Upvotes: 0