【问题标题】:How to limit the scope in which a value is borrowed in Rust? [duplicate]如何限制 Rust 中借用值的范围? [复制]
【发布时间】:2018-11-04 03:33:47
【问题描述】:

我正在尝试在 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 为什么会出现问题?有没有办法让我对这些信息进行编码?

【问题讨论】:

标签: rust borrow-checker


【解决方案1】:

问题在于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&lt;&amp;T&gt; 映射到Option&lt;T&gt;。所以现在v变成String而不是&amp;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()
}

【讨论】:

  • 我喜欢这些解决方案。如果我想坚持最初的想法,基本上实现你在这里展示的功能怎么办?难道我不能写类似的东西:``` { let x; { x = cache.get(key).clone() }; if let Some(v) = x { ... ``` 为什么这不起作用?
  • @simon1505475:因为当你克隆一个Option&lt;&amp;String&gt;时,你仍然有一个Option&lt;&amp;String&gt;。这就是为什么我使用map 取出引用,然后克隆它,因为在引用上调用clone 会克隆引用的对象。但是,我刚刚了解了 Option 的另一个函数,它与 map 所做的一样。 if let Some(v) = cache.get(key).cloned() { ...。 (不是cloned 而不是clone)我将更新我的答案以反映它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-22
  • 2021-03-05
  • 1970-01-01
  • 2018-03-26
相关资源
最近更新 更多