0

カウントを持つタグのベクトルのマージ関数を作成していますが、借用エラーが発生しています。

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. 通常、問題の場所と問題の原因となった以前の移動が表示されますが、ここには表示されません。

私は多くの順列を試しましたが、次の変更でコンパイルできましたが、すべてのクローン作成とタプルの再作成、およびOptions の再作成に満足していません。

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 ほどきれいではありませんが、より近いです。

4

1 に答える 1