Skip to content

Commit

Permalink
Add function core::iter::chain
Browse files Browse the repository at this point in the history
The addition of `core::iter::zip` (#82917) set a precedent for adding
plain functions for iterator adaptors. Adding `chain` makes it a little
easier to `chain` two iterators.

```
for (x, y) in chain(xs, ys) {}
// vs.
for (x, y) in xs.into_iter().chain(ys) {}
```

There is prior art for the utility of this in `itertools::chain`.
  • Loading branch information
rossmacarthur committed Dec 28, 2022
1 parent b38a6d3 commit 21726c3
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 2 deletions.
37 changes: 35 additions & 2 deletions library/core/src/iter/adapters/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use crate::ops::Try;

/// An iterator that links two iterators together, in a chain.
///
/// This `struct` is created by [`Iterator::chain`]. See its documentation
/// for more.
/// This `struct` is created by [`chain`] or [`Iterator::chain`]. See their
/// documentation for more.
///
/// # Examples
///
Expand Down Expand Up @@ -37,6 +37,39 @@ impl<A, B> Chain<A, B> {
}
}

/// Converts the arguments to iterators and links them together, in a chain.
///
/// See the documentation of [`Iterator::chain`] for more.
///
/// # Examples
///
/// ```
/// #![feature(iter_chain)]
///
/// use std::iter::chain;
///
/// let a = [1, 2, 3];
/// let b = [4, 5, 6];
///
/// let mut iter = chain(a, b);
///
/// assert_eq!(iter.next(), Some(1));
/// assert_eq!(iter.next(), Some(2));
/// assert_eq!(iter.next(), Some(3));
/// assert_eq!(iter.next(), Some(4));
/// assert_eq!(iter.next(), Some(5));
/// assert_eq!(iter.next(), Some(6));
/// assert_eq!(iter.next(), None);
/// ```
#[unstable(feature = "iter_chain", reason = "recently added", issue = "none")]
pub fn chain<A, B>(a: A, b: B) -> Chain<A::IntoIter, B::IntoIter>
where
A: IntoIterator,
B: IntoIterator<Item = A::Item>,
{
Chain::new(a.into_iter(), b.into_iter())
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<A, B> Iterator for Chain<A, B>
where
Expand Down
3 changes: 3 additions & 0 deletions library/core/src/iter/adapters/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ pub use self::array_chunks::ArrayChunks;
#[unstable(feature = "std_internals", issue = "none")]
pub use self::by_ref_sized::ByRefSized;

#[unstable(feature = "iter_chain", reason = "recently added", issue = "none")]
pub use self::chain::chain;

#[stable(feature = "iter_cloned", since = "1.1.0")]
pub use self::cloned::Cloned;

Expand Down
2 changes: 2 additions & 0 deletions library/core/src/iter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,8 @@ pub use self::traits::{
DoubleEndedIterator, ExactSizeIterator, Extend, FromIterator, IntoIterator, Product, Sum,
};

#[unstable(feature = "iter_chain", reason = "recently added", issue = "none")]
pub use self::adapters::chain;
#[stable(feature = "iter_zip", since = "1.59.0")]
pub use self::adapters::zip;
#[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")]
Expand Down
8 changes: 8 additions & 0 deletions library/core/tests/iter/adapters/chain.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
use super::*;
use core::iter::*;

#[test]
fn test_chain() {
let xs = [0, 1, 2, 3, 4, 5];
let ys = [30, 40, 50, 60];
let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60];
assert_eq!(Vec::from_iter(chain(xs, ys)), expected);
}

#[test]
fn test_iterator_chain() {
let xs = [0, 1, 2, 3, 4, 5];
Expand Down
1 change: 1 addition & 0 deletions library/core/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
#![feature(slice_partition_dedup)]
#![feature(iter_advance_by)]
#![feature(iter_array_chunks)]
#![feature(iter_chain)]
#![feature(iter_collect_into)]
#![feature(iter_partition_in_place)]
#![feature(iter_intersperse)]
Expand Down

0 comments on commit 21726c3

Please sign in to comment.