i'm trying walk pair of iterators. seems pretty trivial conceptually, expressing has not been.
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 } } }
this not work because left , right moved when match on them. what's way express successfully?
example (also known entire crate):
use std::cmp::{eq, ord, ordering}; pub trait ascendingiterator: iterator <self iterator>::item: eq + ord {} pub trait descendingiterator: iterator <self iterator>::item: eq + ord {} pub struct ascendingintersection<t, t1, t2> t: eq + ord, t1: ascendingiterator<item = t>, t2: ascendingiterator<item = t> { left: t1, right: t2, } impl<t, t1, t2> iterator ascendingintersection<t, t1, t2> 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, } } } }
edit: apologize lazy example; amount of typing can limited unrelated cycling injury.
your match (left, right)
moves values out of left
, right
, they're empty in next iteration. why not move them back?
ordering::less => { left = self.left.next(); right = some(right_value); }, ordering::greater => { left = some(left_value); right = self.right.next(); },
now, that's still bit ugly. nicer way remove match
altogether. first steal try_opt!
- used 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, } ) }
then do
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()), } }
Comments
Post a Comment