有没有办法从传递的 expr 访问 rust 宏中定义的变量?
Is there a way to access variables defined in rust macros from a passed expr?
假设我想让下面的宏工作:
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
});
有没有办法让我可以从 $process
中访问 num
和 foo
?
Rust 宏是 hygienic。这意味着在宏体内定义的标识符不会泄漏出去。
解决此问题的一种方法是修改宏,使其接收标识符作为参数。
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
});
在这里,我使用的语法看起来像一个闭包,这表明 |num, foo|
声明参数(它们实际上声明了变量——足够接近了!)。
另一种方法是使 $process
参数成为宏将调用的文字闭包(或任何可调用表达式),将 num
和 foo
作为参数传递。
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
});
假设我想让下面的宏工作:
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
});
有没有办法让我可以从 $process
中访问 num
和 foo
?
Rust 宏是 hygienic。这意味着在宏体内定义的标识符不会泄漏出去。
解决此问题的一种方法是修改宏,使其接收标识符作为参数。
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
});
在这里,我使用的语法看起来像一个闭包,这表明 |num, foo|
声明参数(它们实际上声明了变量——足够接近了!)。
另一种方法是使 $process
参数成为宏将调用的文字闭包(或任何可调用表达式),将 num
和 foo
作为参数传递。
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
});