我正在尝试编写一个生成结构的宏.结构的实现将由宏生成,但是一些代码块将作为宏参数提供.以下是此类宏的最小示例:
macro_rules! make_struct {
($name:ident $block:block) => {
struct $name {
foo: i32,
}
impl $name {
fn new() -> Self {
$name { foo: 42 }
}
fn act (&self) {
$block
}
}
};
}
Run Code Online (Sandbox Code Playgroud)
以下是如何使用宏的示例:
fn main() {
// Works
make_struct!(Test { println! ("Bar: {:?}", 24); });
let test = Test::new();
test.act();
}
Run Code Online (Sandbox Code Playgroud)
我想提供访问self内部提供的代码.就像是:
fn main() {
// Does not work
make_struct!(Test { println! ("Foo: {:?}", self.foo); });
let test = Test::new();
test.act();
}
Run Code Online (Sandbox Code Playgroud)
据我所知,由于宏观卫生规则,这不起作用.具体而言,self.foo表达式在main函数的语法上下文中进行求值,其中self不存在.问题是:有没有办法修改宏,以便self可以从用户提供的代码访问?
您可以传递闭包而不是块.
make_struct!(Test |this| println!("Foo: {:?}", this.foo));
Run Code Online (Sandbox Code Playgroud)
然后宏可以使用闭包并调用它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)
}
}
};
}
Run Code Online (Sandbox Code Playgroud)
带有let绑定的舞蹈是必要的,因为this无法推断闭包中的类型(还是?).并且当传递闭包之外的其他内容时,它还会使宏的错误报告更具可读性.
| 归档时间: |
|
| 查看次数: |
451 次 |
| 最近记录: |