繁体   English   中英

从创建结构的宏的参数访问self

[英]Access to self from the parameters of a macro that creates a struct

我正在尝试编写一个生成结构的宏。 结构的实现将由宏生成,但是一些代码块将作为宏参数提供。 以下是此类宏的最小示例:

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

操场上的代码

您可以传递闭包而不是块。

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绑定的舞蹈是必要的,因为闭包中的this类型无法推断(但是?)。 并且当传递闭包之外的其他内容时,它还会使宏的错误报告更具可读性。

找到一种方法,通过向宏添加一个参数来存储在块中访问self的名称:

macro_rules! make_struct {
    ($myname:ident : $type_name:ident $block:block) => {
        struct $type_name {
            foo: i32,
        }

        impl $type_name {
            fn new() -> Self {
                $type_name { foo: 42 }
            }
            fn act (&self) {
                let $myname = self;
                $block
            }
        }
    };
}

fn main() {
    make_struct!(myself: Test { println! ("Foo: {:?}", myself.foo); });
    let test = Test::new();
    test.act();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM