From ac8ce300d9673e1c2f4f279cb7f682ab9411c30f Mon Sep 17 00:00:00 2001 From: bluss Date: Sun, 14 Dec 2014 14:54:16 +0100 Subject: [PATCH] Implement Clone for iterator adaptors using functions impl Clone wherever the underlying iterator and the predicate / mapping function implement Clone. For example bare functions impl Clone + FnMut, so such functions used with .map() will produce a clonable iterator. With this change, str's .bytes() iterator becomes clonable. Add a single test that execises .clone() on a Map. --- src/libcore/iter.rs | 106 ++++++++++++++++++++++++++++++++++++++++ src/libcoretest/iter.rs | 9 ++-- 2 files changed, 109 insertions(+), 6 deletions(-) diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 8ee2a8874bb03..cbbe02990a7ba 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -1441,6 +1441,15 @@ impl RandomAccessIterator for Map where } } +impl Clone for Map where + I: Clone + Iterator, + F: Clone + FnMut(A) -> B, +{ + fn clone(&self) -> Map { + Map{iter: self.iter.clone(), f: self.f.clone()} + } +} + /// An iterator which filters the elements of `iter` with `predicate` #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable] @@ -1486,6 +1495,15 @@ impl DoubleEndedIterator for Filter where } } +impl Clone for Filter where + I: Clone + Iterator, + P: Clone + FnMut(&A) -> bool, +{ + fn clone(&self) -> Filter { + Filter{iter: self.iter.clone(), predicate: self.predicate.clone()} + } +} + /// An iterator which uses `f` to both filter and map elements from `iter` #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable] @@ -1534,6 +1552,15 @@ impl DoubleEndedIterator for FilterMap where } } +impl Clone for FilterMap where + I: Clone + Iterator, + F: Clone + FnMut(A) -> Option, +{ + fn clone(&self) -> FilterMap { + FilterMap{iter: self.iter.clone(), f: self.f.clone()} + } +} + /// An iterator which yields the current count and the element during iteration #[deriving(Clone)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] @@ -1677,6 +1704,19 @@ impl Iterator for SkipWhile where I: Iterator, P: FnMut( } } +impl Clone for SkipWhile where + I: Clone + Iterator, + P: Clone + FnMut(&A) -> bool, +{ + fn clone(&self) -> SkipWhile { + SkipWhile { + iter: self.iter.clone(), + flag: self.flag, + predicate: self.predicate.clone() + } + } +} + /// An iterator which only accepts elements while `predicate` is true #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable] @@ -1714,6 +1754,19 @@ impl Iterator for TakeWhile where I: Iterator, P: FnMut( } } +impl Clone for TakeWhile where + I: Clone + Iterator, + P: Clone + FnMut(&A) -> bool, +{ + fn clone(&self) -> TakeWhile { + TakeWhile { + iter: self.iter.clone(), + flag: self.flag, + predicate: self.predicate.clone() + } + } +} + /// An iterator which skips over `n` elements of `iter`. #[deriving(Clone)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] @@ -1864,6 +1917,20 @@ impl Iterator for Scan where } } +impl Clone for Scan where + I: Clone + Iterator, + F: Clone + FnMut(&mut St, A) -> Option, + St: Clone +{ + fn clone(&self) -> Scan { + Scan { + iter: self.iter.clone(), + f: self.f.clone(), + state: self.state.clone() + } + } +} + /// An iterator that maps each element to an iterator, /// and yields the elements of the produced iterators /// @@ -1932,6 +1999,21 @@ impl DoubleEndedIterator for FlatMap where } } +impl Clone for FlatMap where + I: Clone + Iterator, + U: Clone + Iterator, + F: Clone + FnMut(A) -> U, +{ + fn clone(&self) -> FlatMap { + FlatMap { + iter: self.iter.clone(), + f: self.f.clone(), + frontiter: self.frontiter.clone(), + backiter: self.backiter.clone(), + } + } +} + /// An iterator that yields `None` forever after the underlying iterator /// yields `None` once. #[deriving(Clone)] @@ -2075,6 +2157,18 @@ impl RandomAccessIterator for Inspect where } } +impl Clone for Inspect where + I: Iterator + Clone, + F: FnMut(&A) + Clone, +{ + fn clone(&self) -> Inspect { + Inspect { + iter: self.iter.clone(), + f: self.f.clone() + } + } +} + /// An iterator which passes mutable state to a closure and yields the result. /// /// # Example: The Fibonacci Sequence @@ -2141,6 +2235,18 @@ impl Iterator for Unfold where F: FnMut(&mut St) -> Optio } } +impl Clone for Unfold where + St: Clone, + F: Clone + FnMut(&mut St) -> Option +{ + fn clone(&self) -> Unfold { + Unfold { + f: self.f.clone(), + state: self.state.clone() + } + } +} + /// An infinite iterator starting at `start` and advancing by `step` with each /// iteration #[deriving(Clone)] diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index 0bcebe073a3ef..2aa1bc4a56e50 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -675,12 +675,9 @@ fn test_random_access_inspect() { #[test] fn test_random_access_map() { let xs = [1i, 2, 3, 4, 5]; - - let mut it = xs.iter().map(|x| *x); - assert_eq!(xs.len(), it.indexable()); - for (i, elt) in xs.iter().enumerate() { - assert_eq!(Some(*elt), it.idx(i)); - } + fn negate(x: &int) -> int { -*x } + let mut it = xs.iter().map(negate); + check_randacc_iter(it, xs.len()); } #[test]