Is there a way to access variables defined in rust macros from a passed expr?
Assuming I want to make the following macro work:
macro_rules! process_numbers {
($name:ident, $process:expr) => {
let $name: Vec<_> = vec![0, 1, 2].iter().map(|num| {
println!("{}", path); // dummy preprocessing
let foo = 3; // some other preprocessing involving side-effects
$process
}).collect();
}
}
process_numbers!(name, {
num + foo
});
Is there a way so that I could access num
and foo
from within $process
?
Rust macros are hygienic. This means that identifiers defined within a macro's body won't leak out of it.
One way to solve this is to modify the macro such that it receives the identifiers as parameters.
macro_rules! process_numbers {
($name:ident, |$num:ident, $foo: ident| $process:expr) => {
let $name: Vec<_> = vec![0, 1, 2].iter().map(|$num| {
println!("{}", path); // dummy preprocessing
let $foo = 3; // some other preprocessing involving side-effects
$process
}).collect();
}
}
process_numbers!(name, |num, foo| {
num + foo
});
Here, I'm using syntax that looks like a closure, which suggests that |num, foo|
declare parameters (they actually declare variables – close enough!).
Another way would be to make the $process
argument a literal closure (or any invokable expression) that the macro would invoke, passing num
and foo
as arguments.
macro_rules! process_numbers {
($name:ident, $process:expr) => {
let $name: Vec<_> = vec![0, 1, 2].iter().map(|num| {
println!("{}", path); // dummy preprocessing
let foo = 3; // some other preprocessing involving side-effects
$process(num, foo)
}).collect();
}
}
process_numbers!(name, |num, foo| {
num + foo
});