如何说服借用检查器允许我缓存值?

时间:2014-12-25 15:44:56

标签: rust borrow-checker

借阅检查员打败了我:

use std::collections::HashMap;

struct Cache {
    cache: Vec<HashMap<String, String>>,
}

impl Cache {
    fn get(&mut self, index: usize, key: String) -> String {
        let mut cache = &mut self.cache[index];
        match cache.get(&key) {
            Some(r) => {
                return r.clone();
            }
            None => {
                let r = "foo".to_string(); // something smart here
                cache.insert(key, r.clone());
                return r;
            }
        }
    }
}

我得到了什么:

error[E0502]: cannot borrow `*cache` as mutable because it is also borrowed as immutable
  --> src/main.rs:16:17
   |
10 |         match cache.get(&key) {
   |               ----- immutable borrow occurs here
...
16 |                 cache.insert(key, r.clone());
   |                 ^^^^^ mutable borrow occurs here
...
19 |         }
   |         - immutable borrow ends here

如何重写我的代码以便编译?

2 个答案:

答案 0 :(得分:5)

另一种方法是使用entry接口。这种方法的唯一缺点是它(当前)不使用BorrowFrom方法使用的get基础结构,这使其灵活性降低。在您的情况下,这不是问题,因为get获取拥有的密钥。 entry的优点是它只进行一次哈希查找,而使用get强制您进行两次查找。

use std::collections::HashMap;

struct Cache {
    cache: Vec<HashMap<String, String>>,
}

impl Cache {
    fn get(&mut self, index: usize, key: String) -> String {
        self.cache[index]
            .entry(key)
            .or_insert_with(|| "foo".to_string())
            .clone()
    }
}

答案 1 :(得分:2)

借用检查器将cache.get视为不可变借用,尽管它正在返回None。更改代码的最简单方法是将插入移出匹配项,例如:

use std::collections::HashMap;

struct Cache {
    cache: Vec<HashMap<String, String>>,
}

impl Cache {
    fn get(&mut self, index: usize, key: String) -> String {
        let mut cache = &mut self.cache[index];
        match cache.get(&key) {
            Some(r) => {
                return r.clone();
            }
            None => (),
        }
        let r = "foo".to_string(); // something smart here
        cache.insert(key, r.clone());
        return r;
    }
}