Rust ';未解析名称';内部宏';标识';指示符

Rust ';未解析名称';内部宏';标识';指示符,rust,Rust,我正在玩Rust宏系统,以了解它的工作原理。我编写了一个简单的宏,它接受一个标识符并向其中添加一个数字列表 macro_rules! do_your_thing { ( $v:ident; $($e:expr),+ ) => { let mut $v = 0; $( $v += $e; )+ }; } fn main() { do_your_thing!(i; 3, 3, 3); pr

我正在玩Rust宏系统,以了解它的工作原理。我编写了一个简单的宏,它接受一个标识符并向其中添加一个数字列表

macro_rules! do_your_thing {
    ( $v:ident; $($e:expr),+ ) => {
        let mut $v = 0;
        $(
            $v += $e;
        )+
    };
}

fn main() {
    do_your_thing!(i; 3, 3, 3);
    println!("{}", i);
}
如果我运行,编译器将在“$v+=$e;”的宏中的每次重复中三次抱怨“I”是一个未解析的名称

<anon>:5:13: 5:15 error: unresolved name `i`
<anon>:5             $v += $e;
                     ^
在我的初始程序中,它给了我以下输出

fn main /* 67#0 */() {
    let mut i /* 68#4 */ = 0;
    i /* 68#3 */ += 3;
    i /* 68#3 */ += 3;
    i /* 68#3 */ += 3;
}
对DK的修改运行相同的命令会导致

fn main /* 67#0 */() {
    let i /* 68#4 */ =
        {
            let mut i /* 68#5 */ = 0;
            i /* 68#5 */ += 3;
            i /* 68#5 */ += 3;
            i /* 68#5 */ += 3;
            i /* 68#5 */
        };
}

因此,宏中的$(…)+实际上在我原来的宏中引入了一个新的语法上下文。然而,像DK一样,将其包装在一个块中,以某种方式阻止了这种情况的发生。相反,为整个块引入了一个新的语法上下文。

好的,这一个很奇怪。首先,以下是我发现有效的方法:

macro\u规则!做你的事{
($v:ident;$($e:expr),+)=>{
设mut$v={
让mut$v=0;
$(
$v+=$e;
)+
$v
};
};
}
fn main(){
做你自己的事!(i;3,3,3);
println!(“{}”,i);
}
问题是,正如我所知,您的原始宏生成了一组语句,这让编译器感到困惑。将这些语句包装在块中似乎可以解决这一问题

当然,问题是将
let mut$v
放入一个作用域会使下面的
println无法访问它
,因此我还修改了它以从块返回最终值,然后将其分配给新的
$v


老实说,我想不出为什么您的原始代码不应该工作。这可能是一个错误。。。或者它可能是
宏规则的另一个微妙之处我还没找到。很难说。:)

非常有趣。。。真的很奇怪。但是非常感谢。我希望你的解决方案能给我们一个提示,说明这里出了什么问题。
fn main /* 67#0 */() {
    let i /* 68#4 */ =
        {
            let mut i /* 68#5 */ = 0;
            i /* 68#5 */ += 3;
            i /* 68#5 */ += 3;
            i /* 68#5 */ += 3;
            i /* 68#5 */
        };
}