Reputation: 1999
I'm creating a recursive Rust macro that can extract a bang !
from the beginning of an expression.
I can do that just fine like this
macro_rules! test {
(!$e:expr) => {
println!(stringify!($e));
};
}
fn main() {
test!(!'a'); //Outputs: 'a'
}
But has soon as I try to call it from within the macro itself, it no longer works and I get complier errors.
macro_rules! test {
(@process, !$e:expr) => {
println!(stringify!($e));
};
($e:expr) => {
test!(@process, $e);
};
}
fn main() {
test!(!'a');
}
no rules expected the token `!'a'`
I don't think this is a typo because I can directly call it without issue on the second example. Is Rust caching the expression and then not reevaluating it? Can I somehow force Rust to reevaluate it, or is something else happening here?
Upvotes: 1
Views: 98
Reputation: 15002
This is because !'a'
gets parsed as an expression $e
, and when $e
is passed through, it's passed as a whole expression, no longer as a token sequence (so the latter macro invocation will not see !
). You can work around this by capturing it as a raw token sequence instead:
macro_rules! test {
(@process, !$e:expr) => {
println!(stringify!($e));
};
($($e:tt)*) => {
test!(@process, $($e)*);
};
}
Upvotes: 3