rust - How do I modify a value after matching on it? -


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