Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Iterator::collect_into #48597

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions src/libcore/iter/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2463,6 +2463,61 @@ 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
///
/// ```
/// #![feature(collect_into)]
/// 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
///
/// ```
/// #![feature(collect_into)]
/// 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);
/// ```
/// Collecting part of iterator into a vector with manually set capacity
///
/// ```
/// #![feature(collect_into)]
/// let mut iter = 1..5;
/// let first_2 = iter.by_ref()
/// .take(2)
/// .collect_into(Vec::with_capacity(2));
/// let the_rest = iter.collect::<Vec<_>>();
/// assert_eq!(vec![1, 2], first_2);
/// assert_eq!(vec![3, 4], the_rest);
/// ```
#[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);
}

#[stable(feature = "extend_impl_mut_ref", since = "1.26.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);
}
1 change: 1 addition & 0 deletions src/libcore/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#![deny(warnings)]

#![feature(box_syntax)]
#![feature(collect_into)]
#![feature(core_float)]
#![feature(core_private_bignum)]
#![feature(core_private_diy_float)]
Expand Down