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

How can I introduce a copied variable as mutable in a if-let statement?

提问人:pixunil 提问时间:2/5/2017 最后编辑:Shepmasterpixunil 更新时间:11/1/2023 访问量:5014

问:

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

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

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

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

println!("{}", y);

x.insert(0, 0);

这很好用,但如果不在地图中,它就会。由于我不想对这种情况做任何事情,所以我想使用一个(类似于使用的)。panic!3Noneif letwhile 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 上找到,但您需要注释掉第三次尝试,因为它是无效的语法)

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

可变

评论


答:

7赞 user4815162342 2/5/2017 #1

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

if let Some(mut y) = x.get(&3).map(|ref| *ref) {

由于暗示(便宜),您可以使用以下方式表达相同的内容:CopyCloneOption::cloned()

if let Some(mut y) = x.get(&3).cloned() {

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

if let Some(mut y) = x.get(&3).copied() {

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

if let Some(&y) = x.get(&3) {
    let mut y = y;
    ...
2赞 Shepmaster 2/6/2017 #2

您的代码基本上可以工作:

use std::collections::HashMap;

fn main() {
    let mut x: HashMap<i8, i8> = HashMap::new();
    x.insert(1, 6);
    x.insert(3, 5);
    x.insert(5, 1);

    let mut key = 3;
    while let Some(&z) = x.get(&key) {
        key = z;
    }

    println!("{}", key);

    x.insert(key, 0);
}

在这里,作为最后一个不匹配的键。key

评论

0赞 pixunil 2/6/2017
即使它更干净地删除了 ,在我的特定用例中也是必要的。ìf letif