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 435c45e
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 0 deletions.
34 changes: 34 additions & 0 deletions src/lib.rs
Expand Up @@ -346,6 +346,40 @@ 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 {
( $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
6 changes: 6 additions & 0 deletions tests/quick.rs
Expand Up @@ -15,6 +15,7 @@ use itertools::{
EitherOrBoth,
iproduct,
izip,
chain,
};
use itertools::free::{
cloned,
Expand Down Expand Up @@ -526,6 +527,11 @@ quickcheck! {
correct_size_hint(izip!(filt, b.clone(), c.clone())) &&
exact_size(izip!(a, b, c))
}

fn size_chain_macro(a: Iter<i16, Exact>, b: Iter<i16, Exact>, c: Iter<i16, Exact>) -> bool {
correct_size_hint(chain!(a.clone(), b.clone(), c.clone()))
}

fn equal_kmerge(a: Vec<i16>, b: Vec<i16>, c: Vec<i16>) -> bool {
use itertools::free::kmerge;
let mut sa = a.clone();
Expand Down
20 changes: 20 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,25 @@ 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());
}

#[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 435c45e

Please sign in to comment.