不能将 `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
据我所知有三种解决方案。
- 如果你可以使用夜间版本的 Rust,请使用 retain
- 克隆密钥并在 for 循环中使用它
- 迭代两次。第一次迭代时,将要删除的键存储到某个地方,并在第二次迭代时从块中删除这些键
希望有更好的解决方案
据我所知,这个问题有几个解决方案。如果您能够使用夜间功能,则可以在 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
}
}
如果您问我,重要的是理解编译器显示该错误的“原因”,以及上述解决方案为何以及如何解决该问题。一旦你这样做了,经过一些时间和思考,你可能会想出比上面那些更好的解决方案。
如果 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
据我所知有三种解决方案。
- 如果你可以使用夜间版本的 Rust,请使用 retain
- 克隆密钥并在 for 循环中使用它
- 迭代两次。第一次迭代时,将要删除的键存储到某个地方,并在第二次迭代时从块中删除这些键
希望有更好的解决方案
据我所知,这个问题有几个解决方案。如果您能够使用夜间功能,则可以在 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
}
}
如果您问我,重要的是理解编译器显示该错误的“原因”,以及上述解决方案为何以及如何解决该问题。一旦你这样做了,经过一些时间和思考,你可能会想出比上面那些更好的解决方案。