如何在宏中调用self方法?

问题描述 投票:0回答:1
macro_rules! call_on_self {
    ($F:ident) => {
        self.$F()
    }
}

struct F;
impl F {
    fn dummy(&self) {}
    fn test(&self) {
        call_on_self!(dummy);
    }
}

以上不起作用(Playground):

error[E0424]: expected value, found module `self`
  --> src/lib.rs:3:9
   |
3  |         self.$F()
   |         ^^^^ `self` value is a keyword only available in methods with `self` parameter
...
11 |         call_on_self!(dummy);
   |         --------------------- in this macro invocation

我不明白为什么这不起作用:在self可用的方法中调用宏!这有点可能吗?我应该将self传递给宏,否则宏无法解析self

我每晚使用rustc 1.19.0。

rust rust-macros
1个回答
8
投票

Rust宏不仅仅是文本替换。相反,存在一些重要的差异,其中之一是“宏观卫生”。有了这个,宏中的标识符不会干扰外部的标识符,这可以防止像C这样的宏系统经常发生的一些错误。

因此,宏只能访问以下标识符:

  • 明确地传递,或
  • 在定义宏时,它们在范围内。

虽然它看起来似乎是一个不必要的限制,但实际上它有助于代码的可读性。否则,它是“远距离的怪异行动”。这或多或少是相同的原因,为什么将变量的引用传递给函数是通过Rust中的&mut foo完成的,并不像C ++(foo)那样隐式:因为那时,已经很清楚如何在调用站点的函数中使用变量。

这意味着我们有两种方法来解决您的问题。标准解决方案是将self传递给宏:

macro_rules! call_on_self {
    ($self:ident, $F:ident) => {
        $self.$F()
    }
}

struct F;
impl F {
    fn dummy(&self) {}
    fn test(&self) {
        call_on_self!(self, dummy);
    }
}

如果您只需要在test方法中使用宏,则可以在该方法中定义宏。然后,当定义宏时,self已经在范围内,因此它可以在不通过self的情况下工作:

struct F;
impl F {
    fn dummy(&self) {}
    fn test(&self) {
        macro_rules! call_on_self {
            ($F:ident) => {
                self.$F()
            }
        }

        call_on_self!(dummy);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.