不能将 `self.blocks` 借用为可变的,因为它也被借用为不可变的

cannot borrow `self.blocks` as mutable because it is also borrowed as immutable

如果 BTreeMap 的键小于一个值,我想删除 BTreeMap 的键和值:

fn update_confirmed_height(&mut self, new_confirmed_height: u32) {
    assert!(new_confirmed_height >= self.confirmed_height);
    assert!(new_confirmed_height <= self.current_height);

    for height in self.blocks.keys() {
        if height < &new_confirmed_height {
            self.blocks.remove(&height);
        }
    }
}

但是self.blocks.remove(&height)报错: cannot borrow self.blocks as mutable because it is also borrowed as immutable

据我所知有三种解决方案。

  1. 如果你可以使用夜间版本的 Rust,请使用 retain
  2. 克隆密钥并在 for 循环中使用它
  3. 迭代两次。第一次迭代时,将要删除的键存储到某个地方,并在第二次迭代时从块中删除这些键

希望有更好的解决方案

据我所知,这个问题有几个解决方案。如果您能够使用夜间功能,则可以在 BTreeMap 上使用 retain 方法。请参阅:https://doc.rust-lang.org/std/collections/struct.BTreeMap.html#method.retain. LATER EDIT: The latest Rust release (1.53.0) has stabilised the retain method in BTreeMap so this can now be used without nightly features. See https://blog.rust-lang.org/2021/06/17/Rust-1.53.0.html 了解更多信息。

或者,由于您的密钥似乎是 u32,因此可以轻松复制它们。以下几行应该可以解决问题:

    pub fn update_confirmed_height(&mut self, new_confirmed_height: u32) {
        let keys = {
            let mut keys = vec![];
            for (key, _) in self.map.iter() {
                if key < &new_confirmed_height {
                    keys.push(*key);    
                }
            }
            
            keys
        };
        
        for key in keys {
            self.map.remove(&key);
        }
    }

另一个解决方案是改变实际地图本身,并创建一个新地图。至少在我头脑中没有这个快速版本的情况下,这将需要一个值的克隆。

    pub fn update_confirmed_height(&mut self, new_confirmed_height: u32) {
        self.blocks = {
            let mut new_blocks = BTreeMap::new();
            for (key, value) in self.blocks.iter() {
                if key < &new_confirmed_height {
                    new_blocks.insert(*key, value.clone());    
                }
            }
            
            new_blocks
        }
    }

如果您问我,重要的是理解编译器显示该错误的“原因”,以及上述解决方案为何以及如何解决该问题。一旦你这样做了,经过一些时间和思考,你可能会想出比上面那些更好的解决方案。