Skip to content

Commit

Permalink
Add a chain! macro.
Browse files Browse the repository at this point in the history
The chain! macro creates an iterator running multiple iterators
sequentially.
  • Loading branch information
cassiersg committed Feb 4, 2021
1 parent 853f064 commit 6683263
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 0 deletions.
37 changes: 37 additions & 0 deletions src/lib.rs
Expand Up @@ -346,6 +346,43 @@ macro_rules! izip {
};
}

#[macro_export]
/// Create an iterator running multiple iterators sequentially.
///
/// This is a version of the standard ``.chain()`` that's supporting more than
/// two iterators. `chain!` takes `IntoIterator` arguments.
/// Alternatively, this is an alternative to the standard ``.flatten()`` for a
/// fixed number of iterators of distinct sizes.
///
/// **Note:** The result of this macro is in the general case an iterator
/// composed of repeated `.chain()`.
/// The special case of one arguments produce $a.into_iter().
///
///
/// ```
/// # use itertools::chain;
/// #
/// # fn main() {
///
/// // chain three sequences
/// let chained: Vec<i32> = chain!(0..=3, 4..6, vec![6, 7]).collect();
/// assert_eq!(chained, (0..=7).collect::<Vec<i32>>());
/// # }
/// ```
macro_rules! chain {
() => {
core::iter::empty()
};
( $first:expr $(, $rest:expr )* $(,)*) => {
core::iter::IntoIterator::into_iter($first)
$(
.chain(
core::iter::IntoIterator::into_iter($rest)
)
)*
};
}

/// An [`Iterator`] blanket implementation that provides extra adaptors and
/// methods.
///
Expand Down
23 changes: 23 additions & 0 deletions tests/test_core.rs
Expand Up @@ -13,6 +13,7 @@ use crate::it::multizip;
use crate::it::free::put_back;
use crate::it::iproduct;
use crate::it::izip;
use crate::it::chain;

#[test]
fn product2() {
Expand Down Expand Up @@ -87,6 +88,28 @@ fn multizip3() {
}
}

#[test]
fn chain_macro() {
let mut chain = chain!(2..3);
assert!(chain.next() == Some(2));
assert!(chain.next().is_none());

let mut chain = chain!(0..2, 2..3, 3..5i8);
for i in 0..5i8 {
assert_eq!(Some(i), chain.next());
}
assert!(chain.next().is_none());

let mut chain = chain!();
assert_eq!(chain.next(), Option::<()>::None);
}

#[test]
fn chain2() {
let _ = chain!(1.., 2..);
let _ = chain!(1.., 2.., );
}

#[test]
fn write_to() {
let xs = [7, 9, 8];
Expand Down

0 comments on commit 6683263

Please sign in to comment.