我想要更新或添加条目的BTreeMap,具体取决于是否找到密钥。我添加或更新的值可能非常大,所以我想移动它,而不是复制它。然而,无论我尝试什么,Rust的借阅检查器都让我无法做到这一点。
骨架演示程序:
use std::collections::BTreeMap;
#[derive(Debug)]
struct Thing {
value: String
}
fn add_or_update(map: &mut BTreeMap<i32, Thing>, key: i32, value: String) {
// ?????????????????????
// ?? it is a mystery ??
// ?????????????????????
}
fn main() {
let mut container = BTreeMap::<i32, Thing>::new();
add_or_update(&mut container, 42, "Hello!".to_string()); // add
add_or_update(&mut container, 42, "World!".to_string()); // update
println!("{:?}", container);
}
add_or_update
:这显然失败了,因为map
可以为整个匹配表达式可靠地借用:
match map.get_mut(&key) {
Some(ref mut thing) => { thing.value = value; },
None => { map.insert(key, Thing { value: value }); },
}
这是一种借用违规行为,因为map
是为整个if / else表达式借用的,而不只是&#39; if&#39;部分内容:
if let Some(ref mut thing) = map.get_mut(&key) {
thing.value = value;
}
else {
map.insert(key, Thing {
value: value
});
}
这修复了借用违规行为,但也无法正常工作,因为value
现在已经移动到两个地方,Rust编译器不再认为它们是独立的:
let mut updated = false;
if let Some(ref mut thing) = map.get_mut(&key) {
updated = true;
thing.value = value;
}
if !updated {
map.insert(key, Thing {
value: value
});
}
现在我没有想法。有没有办法做到这一点?
如果不是因为我需要移动该值而不是复制它,那么最后一个例子是可行的。
if let
借用整个 if / else表达式的方式令人极为疯狂。为什么它会借用&#34;否则&#34;部分?!?只有在if let
绑定失败时才会运行代码!