匹配后如何修改值?
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)
将值移出 left
和 right
,因此它们在下一次迭代中为空。那为什么不把它们移回去呢?
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()),
}
}
我正在尝试遍历一对迭代器。这在概念上似乎很微不足道,但实际上却没有。
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)
将值移出 left
和 right
,因此它们在下一次迭代中为空。那为什么不把它们移回去呢?
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()),
}
}