【问题标题】:How to end a borrow in a match or if let expression?如何在匹配或 if let 表达式中结束借用?
【发布时间】:2015-11-03 09:49:15
【问题描述】:

我正在使用HashMap 来存储枚举。我想从HashMap 中获取一个值,如果该值是特定的枚举变量,我想将该值的修改后的副本插入到HashMap 中。

我想出的代码是这样的:

if let Node::LeafNode(mut leaf_node) = *(self.pages.get(&page).unwrap()) {
   let mut leaf_node = leaf_node.clone();
   // ...
   self.pages.insert(leaf_page,Node::LeafNode(leaf_node)); 
}

这不会编译,因为self.pages 的借用一直持续到if let-block 的末尾,而self.pages.insert 是可变借用。

我尝试使用值的副本来隐藏HashMap 的值,但这并没有结束借用。通常我会使用{} 块来限制借用,但这在matchif let 中似乎是不可能的。

结束借用以便获得新的可变借用的惯用方式是什么?

【问题讨论】:

    标签: rust


    【解决方案1】:

    目前这是不可能的。你想要的叫做non-lexical borrows,它还没有在 Rust 中实现。同时,您应该使用Entry API 来处理地图——在大多数情况下就足够了。在这种特殊情况下,我不确定条目是否适用,但您始终可以执行类似的操作

    let mut result = None;
    if let Some(&Node::LeafNode(ref leaf_node)) = self.pages.get(&page) {
        let mut leaf_node = leaf_node.clone();
        // ...
        result = Some((leaf_page, leaf_node));
    }
    
    if let Some((leaf_page, leaf_node)) = result {
        self.pages.insert(leaf_page, leaf_node);
    }
    

    鉴于您没有提供Nodeself.pages 的定义,很难使上面的代码完全正确,但它应该大致正确。当然,它只有在leaf_pageleaf_node 不包含对self.pagesself 的引用时才有效,否则您将无法访问self.pages

    【讨论】:

    • 我们真的需要Entry吗?我原以为HashMap::get_mut 应该就足够了。
    • 我不确定这种特殊情况下的条目,但它们确实提供了一种解决一些词汇借用限制的方法,这就是我提到它们的原因。
    • 而且我认为get_mut 在这里还不够,因为修改的是地图本身,而不是值。
    • 是的,你是对的。我认为该代码只是替换了地图中的一个条目,但它正在以不同的键操作一个条目。对不起。
    • 可爱的...作品。对于需要一个选项的生锈新手来说有点意外。在需要的地方有更多的控制结尾借用将是对 Rust 的一个很好的补充。我使用了一个匹配来简化它,但这正是你的建议。谢谢!
    【解决方案2】:

    这是弗拉基米尔使用match 的解决方案:

    let mut result = match self.pages.get(&page) {
        Some(&Node::LeafNode(ref leaf_node)) => Some(leaf_node.clone()),
        _ => None,
    };
    if let Some(leaf_node) = result {
        // ...
        self.pages.insert(page_number, Node::LeafNode(leaf_node));
    };
    

    【讨论】:

      猜你喜欢
      • 2015-07-06
      • 2019-01-26
      • 2014-02-17
      • 2016-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-14
      相关资源
      最近更新 更多