如何在 if-let 语句中将复制的变量引入为可变的?

pix*_*nil 5 mutable rust

我有一个HashMap<i8, i8>可以包含循环的:

let mut x: HashMap<i8, i8> = HashMap::new();
x.insert(1, 6);
x.insert(3, 5);
x.insert(5, 1);
Run Code Online (Sandbox Code Playgroud)

要获得 的最终值3,应该首先查找x[3],然后x[5]最后查找x[1]哪个应该产生6。我决定使用while let循环:

let mut y = x[&3]; // y: i8
while let Some(&z) = x.get(&y) {
    y = z;
}

println!("{}", y);

x.insert(0, 0);
Run Code Online (Sandbox Code Playgroud)

这工作正常,但panic!如果3不在地图上,它就会工作。由于我不想对这种None情况做任何事情,所以我想使用 a if let(类似于while let使用的)。

我尝试过一些符号:

  1. if let Some(&y) = x.get(&3):复制值,但 y 不可变 ( y: i8)
  2. if let Some(mut y) = x.get(&3): y 是可变的,但值是借用的 ( mut y: &i8)
  3. if let mut Some(&y) = x.get(&3):我的目标:可变副本,但语法无效(mut y: i8

(所有变体都可以在Rust Playground中找到,但是您需要注释掉第三次尝试,因为它是无效语法)

我不会争论第二个变体,但我需要将值插入到if let. 由于地图仍然是借来的,我无法再插入。我所需要的只是复制其中的值Some(y)并且y是可变的,以便借用检查器满意并且我可以进行递归查找。

use*_*342 7

你的方法#1 是一个完全正确的匹配,你只需要使y变量可变。一种可能性是转换Option<&i8>为,从而能够在模式中Option<i8>使用。mut y例如,Option::map可以取消引用该值:

if let Some(mut y) = x.get(&3).map(|ref| *ref) {
Run Code Online (Sandbox Code Playgroud)

由于Copy暗示 (cheap) Clone,您可以使用以下方式表达相同的内容Option::cloned()

if let Some(mut y) = x.get(&3).cloned() {
Run Code Online (Sandbox Code Playgroud)

从 Rust 1.35 开始,您可以使用Option::copied(),这保证只复制该值(如果该值不是 ,则无法编译Copy):

if let Some(mut y) = x.get(&3).copied() {
Run Code Online (Sandbox Code Playgroud)

另一种可能性是保持方法 #1 不变,但只需在if let块内引入一个单独的可变变量即可纠正它:

if let Some(&y) = x.get(&3) {
    let mut y = y;
    ...
Run Code Online (Sandbox Code Playgroud)