如何限制在Rust中借入值的范围?

时间:2018-11-04 03:33:48

标签: rust borrow-checker

我正在尝试在Rust中做一些记笔记,并且违反了借阅检查器。

fn calc_deps(cache: &mut HashMap<String, String>, key: &String) -> String {
    if let Some(v) = cache.get(key) {
        v
    } else {
        let r = /* computations */
        cache.insert(key.clone(),r.clone());
        r
    }
}

我被告知缓存被借用了两次。如果我在插入之前就完成了对get的操作,为什么会出现问题?我有办法对这些信息进行编码吗?

1 个答案:

答案 0 :(得分:3)

问题在于,v的生存期是整个if/else块的有效期,即使else部分中不可用。您可以借助Option::cloned来解决此问题。

pub fn calc_deps(cache: &mut HashMap<String, String>, key: &String) -> String {
    if let Some(v) = cache.get(key).cloned() {
        v
    } else {
        let r = String::from("computations");
        cache.insert(key.clone(), r.clone());
        r
    }
}

Option::cloned通过克隆内容将Option<&T>映射到Option<T>。因此,现在v变成了String而不是&String,并且不再借用cache

另一种选择是使用HashMap::entry/or_insert_with界面。可能更惯用了,但是它需要无条件地克隆key

pub fn calc_deps(cache: &mut HashMap<String, String>, key: String) -> String {
    cache
        .entry(key)
        .or_insert_with(|| String::from("computations"))
        .clone()
}

您也可以简单地使用or_insert而不是or_insert_with,但这将需要无条件地为r进行计算。

pub fn calc_deps(cache: &mut HashMap<String, String>, key: String) -> String {
    cache
        .entry(key)
        .or_insert(String::from("computations"))
        .clone()
}