Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 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);
/// ```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good example.. perhaps include a bit longer example as well which is more real-worldy?

/// 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 = "rust1", since = "1.26.0")]
impl <'a, A, E: Extend<A>> Extend<A> for &'a mut E {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we really do this? Regardless of crater, RFC 1023 calls &mut T a fundamental type, "where implementing a blanket impl [...] is a breaking change."

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cuviper yeah I do believe it's a breaking change technically, but if it doesn't actually break anything in practice we may have leeway to land it.

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