无法将`self.hash`作为可变借用,因为它同时被作为不可变借用。

4

我正在尝试使此工作生效

use std::collections::HashMap;

struct Test1 {
    total: u32,
    hash: HashMap<u32, u32>,
}

impl Test1 {
    fn new() -> Test1 {
        Test1 {
            total: 0,
            hash: HashMap::new(),
        }
    }

    fn add(&mut self) -> u32 {
        self.total += 1;
        self.total
    }

    fn get_or_create(&mut self, id: u32) -> u32 {
        match self.hash.get(&id) {
            Some(value) => *value,
            None => {
                let value = self.add();
                self.hash.insert(id, value);
                value
            }
        }
    }
}

fn main() {
    let mut test = Test1::new();
    println!("{:?}", test.get_or_create(1));
    println!("{:?}", test.get_or_create(1));
}

(playpen)[http://is.gd/hDLEaL]

但我得到了

<anon>:25:33: 25:37 error: cannot borrow `*self` as mutable because `self.hash` is also borrowed as immutable [E0502]

删除模式匹配并不能解决问题,但我不明白为什么。


2
尝试将 match self.hash.get(&id) { 改为 match self.hash.get(&id).cloned() {,并将 *value 改为 value - qthree
谢谢,这很有意义。它有效了!! - TlmaK0
1
这是因为get返回的是Option<&u32>,但实际上你不需要那个借用引用,只需要值。所以cloned()Option<&T>转换为Option<T>并释放了借用。 - qthree
3
你想要做的更好的方式有一个更好的习语,.entry().or_insert():https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.entry - starblue
1
高度相关 - Shepmaster
1个回答

9

更新

在Rust中添加了非词法生命周期,如果您正在使用Rust 2018版的1.31.0和Rust 2015版的1.36.0,这个问题就不再是一个问题。

原始答案

当前Rust语言存在一个问题,即借用(borrows)始终是词法作用域的。也就是说,它们在整个 {} 或块作用域中都有效。在match表达式中,对self执行的借用会延续到SomeNone块中。解决这个问题最简单的方法是使用if let语句。它提供了模式匹配,并允许你在两个块中都使用self

代码

use std::collections::HashMap;

struct Test1 {
    total: u32,
    hash: HashMap<u32, u32>,
}

impl Test1 {
    fn new() -> Test1 {
        Test1 {
            total: 0,
            hash: HashMap::new(),
        }
    }

    fn add(&mut self) -> u32 {
        self.total += 1;
        self.total
    }

    fn get_or_create(&mut self, id: u32) -> u32 {
        if let Some(&value) = self.hash.get(&id) {
            value
        } else {
            let value = self.add();
            self.hash.insert(id, value);
            value
        }
    }
}

fn main() {
    let mut test = Test1::new();
    println!("{:?}", test.get_or_create(1));
    println!("{:?}", test.get_or_create(1));
}

非常感谢您。我以为我要疯了。 - John H

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