我正在尝试编写一个生成结构的宏。该结构的实现将由宏生成,但一些代码块将作为宏参数提供。这是此类宏的最小示例:
macro_rules! make_struct {
($name:ident $block:block) => {
struct $name {
foo: i32,
}
impl $name {
fn new() -> Self {
$name { foo: 42 }
}
fn act (&self) {
$block
}
}
};
}
下面是如何使用宏的示例:
fn main() {
// Works
make_struct!(Test { println! ("Bar: {:?}", 24); });
let test = Test::new();
test.act();
}
我想在提供的代码中授予对 self
的访问权限。像这样的东西:
fn main() {
// Does not work
make_struct!(Test { println! ("Foo: {:?}", self.foo); });
let test = Test::new();
test.act();
}
我知道这不起作用,因为宏观卫生规则。具体来说,self.foo
表达式是在 main
函数的语法上下文中计算的,其中 self
不存在。问题是:有没有办法修改宏,以便可以从用户提供的代码访问 self
?
最佳答案
您可以传递闭包而不是 block 。
make_struct!(Test |this| println!("Foo: {:?}", this.foo));
然后宏可以使用闭包并用self
调用它:
macro_rules! make_struct {
($name:ident $closure:expr) => {
struct $name {
foo: i32,
}
impl $name {
fn new() -> Self {
$name { foo: 42 }
}
fn act (&self) {
let x: &Fn(&Self) = &$closure;
x(self)
}
}
};
}
与 let 绑定(bind)的舞蹈是必要的,因为无法推断闭包中 this
的类型(还?)。当传递闭包以外的内容时,它还使宏的错误报告更具可读性。
关于rust - 从创建结构的宏的参数访问 self,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36056408/