在Rust中多次使用相同变量名的let关键字

3

我刚接触Rust,已经过了被借用检查器卡住的阶段,但是我现在遇到了另一个问题,就是为什么这段代码能够工作或者通过。我正在实现一个类似结构体的枚举类型,它充当一种可以添加到节点的形式:

#[derive(Debug)]
enum Node {
    Val {num:u32, next:Box<Node>},
    Nil
}

impl Node {
    fn put_next(&self, i:u32) -> Node {
       match self {
           Node::Val {num, next:_} => Node::Val {num:*num, next:Box::new(Node::Val {num:i, next:Box::new(Node::Nil)})},
           Node::Nil => Node::Val {num:i, next:Box::new(Node::Nil)}
       }
    }
}

以下的main函数显然无法使用,因为你不能对一个不可变的变量进行赋值:
fn main() {
   let foo = Node::Val {num:5, next:Box::new(Node::Nil)};
   foo = foo.put_next(30);
   println!("foo {:?} ", foo);
}

然而,如果我再次使用 let 来定义 foo,代码就可以正常运行,没有错误!
fn main() {
   let foo = Node::Val {num:5, next:Box::new(Node::Nil)};
   let foo = foo.put_next(30);
   println!("foo {:?} ", foo);
}
// foo Val { num: 5, next: Val { num: 30, next: Nil } } 

我的问题是,为什么编译器允许使用let多次声明同一个变量?如果这是有意的,那意味着什么?它会在幕后创建一个名为foo的新变量并丢弃旧的吗?


1个回答

7
这被称为变量遮蔽。第二个foo没有绑定到与第一个相同的值,而是完全新的值。有关更多详细信息,请查看Rust Book的Shadowing章节,即:

[...]您可以声明与先前变量相同名称的新变量,新变量会遮蔽先前的变量。 Rustaceans表示第一个变量被第二个变量遮蔽,这意味着在使用变量时出现第二个变量的值。


Shadowing是指在不同的作用域中存在两个具有相同名称的变量。这只是变量名称的重新绑定。 - Simon Whitehead
1
@SimonWhitehead 如您在《The Book》中所见,这被称为阴影化。 - Peter Varo
公正的观点 - 我道歉。Rust书籍似乎也在同一作用域中定义了阴影。 - Simon Whitehead

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接