From 7bb4ff62672178c220a945129a2110b91f78d47f Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Fri, 5 Jul 2013 13:00:11 -0400 Subject: [PATCH] iterator: Add `IteratorUtil::peek_` method --- src/libstd/iterator.rs | 65 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/src/libstd/iterator.rs b/src/libstd/iterator.rs index b164bcbd28b3c..08ccf4fc2553b 100644 --- a/src/libstd/iterator.rs +++ b/src/libstd/iterator.rs @@ -245,6 +245,25 @@ pub trait IteratorUtil { fn flat_map_<'r, B, U: Iterator>(self, f: &'r fn(A) -> U) -> FlatMapIterator<'r, A, B, Self, U>; + /// Creates an iterator that calls a function with a reference to each + /// element before yielding it. This is often useful for debugging an + /// iterator pipeline. + /// + /// # Example + /// + /// ~~~ {.rust} + ///let xs = [1u, 4, 2, 3, 8, 9, 6]; + ///let sum = xs.iter() + /// .transform(|&x| x) + /// .peek_(|&x| debug!("filtering %u", x)) + /// .filter(|&x| x % 2 == 0) + /// .peek_(|&x| debug!("%u made it through", x)) + /// .sum(); + ///println(sum.to_str()); + /// ~~~ + // FIXME: #5898: should be called `peek` + fn peek_<'r>(self, f: &'r fn(&A)) -> PeekIterator<'r, A, Self>; + /// An adaptation of an external iterator to the for-loop protocol of rust. /// /// # Example @@ -442,6 +461,12 @@ impl> IteratorUtil for T { FlatMapIterator{iter: self, f: f, subiter: None } } + // FIXME: #5898: should be called `peek` + #[inline] + fn peek_<'r>(self, f: &'r fn(&A)) -> PeekIterator<'r, A, T> { + PeekIterator{iter: self, f: f} + } + /// A shim implementing the `for` loop iteration protocol for iterator objects #[inline] fn advance(&mut self, f: &fn(A) -> bool) -> bool { @@ -1041,6 +1066,32 @@ impl<'self, A, T: Iterator, B, U: Iterator> Iterator for } } +/// An iterator that calls a function with a reference to each +/// element before yielding it. +pub struct PeekIterator<'self, A, T> { + priv iter: T, + priv f: &'self fn(&A) +} + +impl<'self, A, T: Iterator> Iterator for PeekIterator<'self, A, T> { + #[inline] + fn next(&mut self) -> Option { + let next = self.iter.next(); + + match next { + Some(ref a) => (self.f)(a), + None => () + } + + next + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + self.iter.size_hint() + } +} + /// An iterator which just modifies the contained state throughout iteration. pub struct UnfoldrIterator<'self, A, St> { priv f: &'self fn(&mut St) -> Option, @@ -1236,6 +1287,20 @@ mod tests { assert_eq!(i, ys.len()); } + #[test] + fn test_peek() { + let xs = [1u, 2, 3, 4]; + let mut n = 0; + + let ys = xs.iter() + .transform(|&x| x) + .peek_(|_| n += 1) + .collect::<~[uint]>(); + + assert_eq!(n, xs.len()); + assert_eq!(xs, ys.as_slice()); + } + #[test] fn test_unfoldr() { fn count(st: &mut uint) -> Option {