From f1eef5c2f501e89c6c1e1638d89fafd3bd51608e Mon Sep 17 00:00:00 2001 From: CodeSandwich Date: Wed, 28 Feb 2018 01:16:14 +0100 Subject: [PATCH] Add Iterator::collect_into and impl Extend for &mut Extend --- src/libcore/iter/iterator.rs | 41 ++++++++++++++++++++++++++++++++++++ src/libcore/iter/traits.rs | 12 +++++++++++ src/libcore/tests/iter.rs | 28 ++++++++++++++++++++++++ 3 files changed, 81 insertions(+) diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 9d8a71250f88a..487f1c1f3f6de 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -2463,6 +2463,47 @@ pub trait Iterator { } } } + + /// Collects all items from iterator into a collection. + /// + /// This method consumes the iterator and includes all its items to the + /// passed collection. The collection is then returned, so the call chain + /// can be continued. Collections can be passed and returned either by + /// value or by mutable reference. + /// + /// This method is a counter-part of [Extend::extend](trait.Extend.html), + /// but instead of being called on collection, it's called on iterator. + /// + /// # Examples + /// Basic usage on collection passed by value + /// + /// ``` + /// let result = (3..5).collect_into(vec![1, 2]); + /// assert_eq!(vec![1, 2, 3, 4], result); + /// ``` + /// More complex usage on collection passed by mutable reference + /// + /// ``` + /// let primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43]; + /// let mut vec_3 = vec![33, 53]; + /// let vec_103 = primes.into_iter() + /// .cloned() + /// .filter(|p| p % 10 == 3) + /// .collect_into(&mut vec_3) + /// .iter() + /// .map(|i| i + 100) + /// .collect::>(); + /// assert_eq!(vec![33, 53, 3, 13, 23, 43], vec_3); + /// assert_eq!(vec![133, 153, 103, 113, 123, 143], vec_103); + /// ``` + #[unstable(feature = "collect_into", issue = "0")] + fn collect_into(self, mut collection: E) -> E where + E: Extend, + Self: Sized + { + collection.extend(self); + collection + } } /// Select an element from an iterator based on the given "projection" diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 860742d9eab60..810445da7d082 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -267,6 +267,11 @@ impl IntoIterator for I { /// or, in the case of collections that permit multiple entries with equal /// keys, that entry is inserted. /// +/// When extending with items from [Iterator](trait.Iterator.html), it's often +/// more convenient to use +/// [Iterator::collect_into](trait.Iterator.html#method.collect_into). It works +/// exactly the same way, but is called on series instead of collection. +/// /// # Examples /// /// Basic usage: @@ -352,6 +357,13 @@ pub trait Extend { fn extend>(&mut self, iter: T); } +#[unstable(feature = "collect_into", issue = "0")] +impl <'a, A, E: Extend> Extend for &'a mut E { + fn extend>(&mut self, iter: T) { + (*self).extend(iter) + } +} + /// An iterator able to yield elements from both ends. /// /// Something that implements `DoubleEndedIterator` has one extra capability diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index edd75f7795ed7..b2aa288ae3d2c 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -2084,3 +2084,31 @@ fn test_monad_laws_associativity() { assert_eq!((0..10).flat_map(f).flat_map(g).sum::(), (0..10).flat_map(|x| f(x).flat_map(g)).sum::()); } + +#[test] +fn test_collect_into_passed_by_value() { + let collection = vec![1, 2]; + + let result = (3..5).collect_into(collection); + + assert_eq!(vec![1, 2, 3, 4], result); +} + +#[test] +fn test_collect_into_passed_by_mut_ref() { + let mut collection = vec![1, 2]; + + let result = (3..5).collect_into(&mut collection) as * const _; + + assert_eq!(&collection as *const _, result); + assert_eq!(vec![1, 2, 3, 4], collection); +} + +#[test] +fn test_extend_impl_for_mut_ref_extend() { + let mut collection = vec![1, 2]; + + (&mut collection).extend(3..5); + + assert_eq!(vec![1, 2, 3, 4], collection); +}