【问题标题】:Is there a way to reference a local variable within a Rust macro?有没有办法在 Rust 宏中引用局部变量?
【发布时间】:2020-11-30 14:49:26
【问题描述】:

我想使用宏来生成函数的主体,但这样做需要访问本地范围内的变量:

macro_rules! generate_func {
    ($name:ident) => {
        fn $name(param: i32) {
            generate_body!()
        }
    };
}

macro_rules! generate_body {
    () => {
        println!("{}", &param);
    }
}

generate_func!(foo);
error[E0425]: cannot find value `param` in this scope
  --> src/lib.rs:11:25
   |
11 |         println!("{}", &param);
   |                         ^^^^^ not found in this scope
...
15 | generate_func!(foo);
   | -------------------- in this macro invocation
   |
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

Playground link

这不起作用非常令人沮丧,因为我可以运行cargo-expand并看到生成的代码是有效的:

fn foo(param: i32) {

    {
        ::std::io::_print(::core::fmt::Arguments::new_v1(&["", "\n"],
                                                         &match (&&param,) {
                                                              (arg0,) =>
                                                              [::core::fmt::ArgumentV1::new(arg0,
                                                                                            ::core::fmt::Display::fmt)],
                                                          }));
    }
}

(由于println!,这有点乱,但你可以在那里看到有效的参考)

我什至可以将扩展复制并粘贴到我的源代码中,编译器会接受它。肯定有一些方法可以达到预期的结果吗?

似乎与以下内容大致相关:

但我不能确定我是否遇到了完全相同的问题;我的情况似乎更基本。

【问题讨论】:

    标签: rust macros


    【解决方案1】:

    Rust 宏是 hygienic,它可以防止标识符从一个范围泄漏到另一个范围并造成各种混乱。但是你可以通过将paramgenerate_func 传递到generate_body 来解决这个特殊问题:

    macro_rules! generate_func {
        ($name:ident) => {
            fn $name(param: i32) {
                generate_body!(param)
            }
        };
    }
    
    macro_rules! generate_body {
        ($param:ident) => {
            println!("{}", &$param);
        }
    }
    
    generate_func!(foo);
    

    Playground 上查看。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-30
      • 2013-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-27
      相关资源
      最近更新 更多