无法在宏中使用 self,因为宏扩展忽略标记“self”

Posted

技术标签:

【中文标题】无法在宏中使用 self,因为宏扩展忽略标记“self”【英文标题】:Unable to use self in macro because the macro expansion ignores token `self` 【发布时间】:2017-03-28 08:25:49 【问题描述】:

我想编写一个打印“OK”然后在方法中返回 self 的宏。这是我的第一个宏,所以我尝试了这个,认为它只会进行文本替换,但它失败了:

macro_rules! print_ok_and_return_self 
    () => 
        println!("OK");
        self
    


fn main() 
    let a = A;
    a.a().a();


struct A 

impl A 
    fn a(self) -> Self 
        print_ok_and_return_self!()
    

错误:

error: macro expansion ignores token `self` and any following
 --> src/main.rs:4:13
  |
4 |             self
  |             ^^^^
  |
note: caused by the macro expansion here; the usage of `print_ok_and_return_self!` is likely invalid in expression context
 --> src/main.rs:17:13
  |
17|             print_ok_and_return_self!()
  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^

快速浏览文档后,我知道这不仅仅是文本替换,但我仍然不知道如何使它工作。

【问题讨论】:

【参考方案1】:

连续出现两个错误,先修复第一个。

宏臂的语法是:

(...) => 
    ...

这意味着您的宏扩展为:

println!("OK");
self

这不行(两个陈述)。

相反,它应该扩展为一个表达式(在这种情况下),您可以通过将其包含在 中来获得:

macro_rules! print_ok_and_return_self 
    () => 
        
            println!("OK");
            self
        
    

这导致第二个错误:

error[E0424]: `self` is not available in a static method
  --> <anon>:4:9
   |
4  |         self
   |         ^^^^ not available in static method
...
17 |         print_ok_and_return_self!()
   |         --------------------------- in this macro invocation
   |
   = note: maybe a `self` argument is missing?

宏不能假定其范围内存在变量,因此您需要将self 作为参数传递:

macro_rules! print_ok_and_return_value 
    ($v:expr) => 
        println!("OK");
        $v
    

然后调用变成:

impl A 
    fn a(self) -> Self 
        print_ok_and_return_value!(self)
    

【讨论】:

以上是关于无法在宏中使用 self,因为宏扩展忽略标记“self”的主要内容,如果未能解决你的问题,请参考以下文章

Symfony 3在宏中使用宏?

Lisp:在宏中扩展属性名称

在宏中拆分字符串

确保每个字符串文字都包含在宏中

在宏中过度使用会损害性能吗?

如何在宏中调用自身的方法?