Skip to content

Commit

Permalink
Add Iterator::collect_into and impl Extend for &mut Extend
Browse files Browse the repository at this point in the history
  • Loading branch information
CodeSandwich committed Mar 4, 2018
1 parent 29f5c69 commit f1eef5c
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 0 deletions.
41 changes: 41 additions & 0 deletions src/libcore/iter/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<Vec<_>>();
/// 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<E>(self, mut collection: E) -> E where
E: Extend<Self::Item>,
Self: Sized
{
collection.extend(self);
collection
}
}

/// Select an element from an iterator based on the given "projection"
Expand Down
12 changes: 12 additions & 0 deletions src/libcore/iter/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,11 @@ impl<I: Iterator> 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:
Expand Down Expand Up @@ -352,6 +357,13 @@ pub trait Extend<A> {
fn extend<T: IntoIterator<Item=A>>(&mut self, iter: T);
}

#[unstable(feature = "collect_into", issue = "0")]
impl <'a, A, E: Extend<A>> Extend<A> for &'a mut E {
fn extend<T: IntoIterator<Item=A>>(&mut self, iter: T) {
(*self).extend(iter)
}
}

/// An iterator able to yield elements from both ends.
///
/// Something that implements `DoubleEndedIterator` has one extra capability
Expand Down
28 changes: 28 additions & 0 deletions src/libcore/tests/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2084,3 +2084,31 @@ fn test_monad_laws_associativity() {
assert_eq!((0..10).flat_map(f).flat_map(g).sum::<usize>(),
(0..10).flat_map(|x| f(x).flat_map(g)).sum::<usize>());
}

#[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);
}

0 comments on commit f1eef5c

Please sign in to comment.