匹配后如何修改值?

How do I modify a value after matching on it?

我正在尝试遍历一对迭代器。这在概念上似乎很微不足道,但实际上却没有。

fn next(&mut self) -> Option<Self::Item> {
    let mut left = self.left.next();
    let mut right = self.right.next();

    loop {
        match (left, right) {
            (Some(left_value), Some(right_value)) => {
                match left_value.cmp(&right_value) {
                    Ordering::Equal => return Some((left_value, right_value)),
                    Ordering::Less => left = self.left.next(),
                    Ordering::Greater => right = self.right.next(),
                }
            }

            _ =>  return None
        }
    }
}

这不起作用,因为当我匹配它们时左右移动了。有什么方法可以成功表达?

示例(也称为整个板条箱):

use std::cmp::{Eq, Ord, Ordering};

pub trait AscendingIterator: Iterator where <Self as Iterator>::Item: Eq + Ord {}

pub trait DescendingIterator: Iterator where <Self as Iterator>::Item: Eq + Ord {}

pub struct AscendingIntersection<T, T1, T2>
    where T: Eq + Ord,
          T1: AscendingIterator<Item = T>,
          T2: AscendingIterator<Item = T>
{
    left: T1,
    right: T2,
}

impl<T, T1, T2> Iterator for AscendingIntersection<T, T1, T2>
    where T: Eq + Ord,
          T1: AscendingIterator<Item = T>,
          T2: AscendingIterator<Item = T>
{
    type Item = (T, T);

    fn next(&mut self) -> Option<Self::Item> {
        let mut left = self.left.next();
        let mut right = self.right.next();

        loop {
            match (left, right) {
                (Some(left_value), Some(right_value)) => {
                    match left_value.cmp(&right_value) {
                        Ordering::Equal => return Some((left_value, right_value)),
                        Ordering::Less => left = self.left.next(),
                        Ordering::Greater => right = self.right.next(),
                    }
                }

                _ => return None,
            }
        }
    }
}

编辑:对于这个懒惰的例子,我深表歉意;我可以打字的次数受到无关的骑自行车伤害的限制。

您的 match (left, right) 将值移出 leftright,因此它们在下一次迭代中为空。那为什么不把它们移回去呢?

Ordering::Less => {
    left = self.left.next();
    right = Some(right_value);
},
Ordering::Greater => {
    left = Some(left_value);
    right = self.right.next();
},

现在,这还是有点难看。一个更好的方法是完全删除 match。先偷一个try_opt!——我用的是http://crumblingstatue.github.io/doc/try_opt/src/try_opt/lib.rs.html#1-37

macro_rules! try_opt {
    ($e:expr) =>(
        match $e {
            Some(v) => v,
            None => return None,
        }
    )
}

那就干

let mut left = try_opt!(self.left.next());
let mut right = try_opt!(self.right.next());

loop {
    match left.cmp(&right) {
        Ordering::Equal => return Some((left, right)),
        Ordering::Less => left = try_opt!(self.left.next()),
        Ordering::Greater => right = try_opt!(self.right.next()),
    }
}