カウントを持つタグのベクトルのマージ関数を作成していますが、借用エラーが発生しています。
fn merge(mut l1: Vec<(String, u32)>, mut l2: Vec<(String, u32)>) -> Vec<(String, u32)> {
let mut d1 = l1.drain(..);
let mut d2 = l2.drain(..);
let mut result = Vec::new();
let mut v1 = d1.next();
let mut v2 = d2.next();
loop {
match (v1, v2) {
(None, None) => return result,
(None, Some(x)) => {
result.push(x.clone());
v2 = d2.next()
}
(Some(x), None) => {
result.push(x.clone());
v1 = d1.next()
}
(Some(p1), Some(p2)) => {
let (ref s1, t1) = p1;
let (ref s2, t2) = p2;
if s1 == s2 {
result.push((s1.clone(), t1 + t2));
v1 = d1.next();
v2 = d2.next();
} else if s1 < s2 {
result.push(p1.clone());
v1 = d1.next();
} else {
result.push(p2.clone());
v2 = d2.next();
}
}
}
}
}
エラーが発生します:
error: use of moved value: `v1` [E0382]
match (v1,v2) {
^~
help: run `rustc --explain E0382` to see a detailed explanation
note: `v1` was previously moved here because it has type `core::option::Option<(collections::string::String, u32)>`, which is non-copyable
同様のエラーがv2
. 通常、問題の場所と問題の原因となった以前の移動が表示されますが、ここには表示されません。
私は多くの順列を試しましたが、次の変更でコンパイルできましたが、すべてのクローン作成とタプルの再作成、およびOption
s の再作成に満足していません。
match (v1, v2) {
(None, None) => return result,
(None, Some(x)) => {
result.push(x.clone());
v1 = None;
v2 = d2.next();
}
(Some(x), None) => {
result.push(x.clone());
v1 = d1.next();
v2 = None;
}
(Some(p1), Some(p2)) => {
let (ref s1, t1) = p1;
let (ref s2, t2) = p2;
if s1 == s2 {
result.push((s1.clone(), t1 + t2));
v1 = d1.next();
v2 = d2.next();
} else if s1 < s2 {
result.push(p1.clone());
v1 = d1.next();
v2 = Some((s2.clone(), t2));
} else {
result.push(p2.clone());
v1 = Some((s1.clone(), t1));
v2 = d2.next();
}
}
}
誰かが借用チェッカーの挑戦を探している場合に備えて、参考までに、私が本当に書きたいことを追加します。
fn merge(mut l1: Vec<(String, u32)>, mut l2: Vec<(String, u32)>) -> Vec<(String, u32)> {
let mut d1 = l1.drain(..);
let mut d2 = l2.drain(..);
let mut result = Vec::new();
let mut v1 = d1.next();
let mut v2 = d2.next();
loop {
match (v1, v2) {
(None, None) => return result,
(None, Some(p2)) => {
result.push(p2);
v1 = None;
v2 = d2.next()
}
(Some(p1), None) => {
result.push(p1);
v1 = d1.next();
v2 = None
}
(Some(p1 @ (s1, _)), o2 @ Some((s2, _))) if s1 < s2 => {
result.push(p1);
v1 = d1.next();
v2 = o2
}
(o1 @ Some((s1, _)), Some(p2 @ (s2, _))) if s1 > s2 => {
result.push(p2);
v1 = o1;
v2 = d2.next()
}
(Some((s1, t1)), Some((_, t2))) => {
result.push((s1, t1 + t2));
v1 = d1.next();
v2 = d2.next()
}
}
}
}
(v1, v2)
各パスが強制的にv1
およびに設定されるように、一致 オン は値を移動する必要があることに注意してくださいv2
。まだ Haskell ほどきれいではありませんが、より近いです。