Skip to content

Commit c75c407

Browse files
cassiersgjswrenn
andauthored
Apply suggestions from code review
Co-authored-by: Jack Wrenn <me@jswrenn.com>
1 parent 6683263 commit c75c407

File tree

1 file changed

+49
-20
lines changed

1 file changed

+49
-20
lines changed

src/lib.rs

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -347,39 +347,68 @@ macro_rules! izip {
347347
}
348348

349349
#[macro_export]
350-
/// Create an iterator running multiple iterators sequentially.
350+
/// [Chain][`chain`] zero or more iterators together into one sequence.
351351
///
352-
/// This is a version of the standard ``.chain()`` that's supporting more than
353-
/// two iterators. `chain!` takes `IntoIterator` arguments.
354-
/// Alternatively, this is an alternative to the standard ``.flatten()`` for a
355-
/// fixed number of iterators of distinct sizes.
352+
/// The comma-separated arguments must implement [`IntoIterator`].
353+
/// The final argument may be followed by a trailing comma.
356354
///
357-
/// **Note:** The result of this macro is in the general case an iterator
358-
/// composed of repeated `.chain()`.
359-
/// The special case of one arguments produce $a.into_iter().
355+
/// [`chain`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.chain
356+
/// [`IntoIterator`]: https://doc.rust-lang.org/std/iter/trait.IntoIterator.html
357+
///
358+
/// # Examples
360359
///
360+
/// [`iter::empty`]: https://doc.rust-lang.org/std/iter/fn.empty.html
361361
///
362+
/// Empty invocations of `chain!` expand to an invocation of [`iter::empty`]:
362363
/// ```
363-
/// # use itertools::chain;
364-
/// #
365-
/// # fn main() {
364+
/// # use std::iter;
365+
/// use itertools::chain;
366366
///
367-
/// // chain three sequences
368-
/// let chained: Vec<i32> = chain!(0..=3, 4..6, vec![6, 7]).collect();
369-
/// assert_eq!(chained, (0..=7).collect::<Vec<i32>>());
370-
/// # }
367+
/// let _: iter::Empty<()> = chain!();
368+
/// let _: iter::Empty<i8> = chain!();
369+
/// ```
370+
///
371+
/// Invocations of `chain!` with one argument expand to [`arg.into_iter()`][`IntoIterator`]:
372+
/// ```
373+
/// use std::{ops::Range, slice};
374+
/// use itertools::chain;
375+
/// let _: <Range<_> as IntoIterator>::IntoIter = chain!((2..6),); // trailing comma optional!
376+
/// let _: <&[_] as IntoIterator>::IntoIter = chain!(&[2, 3, 4]);
377+
/// ```
378+
///
379+
/// Invocations of `chain!` with multiple arguments [`.into_iter()`][`IntoIterator`] each
380+
/// argument, and then [`chain`] them together:
381+
/// ```
382+
/// use std::{iter::*, ops::Range, slice};
383+
/// use itertools::{assert_equal, chain};
384+
///
385+
/// // e.g., this:
386+
/// let with_macro: Chain<Chain<Once<_>, Take<Repeat<_>>>, slice::Iter<_>> =
387+
/// chain![once(&0), repeat(&1).take(2), &[2, 3, 5],];
388+
///
389+
/// // ...is equivalant to this:
390+
/// let with_method: Chain<Chain<Once<_>, Take<Repeat<_>>>, slice::Iter<_>> =
391+
/// once(&0)
392+
/// .chain(repeat(&1).take(2))
393+
/// .chain(&[2, 3, 5]);
394+
///
395+
/// assert_equal(with_macro, with_method);
371396
/// ```
372397
macro_rules! chain {
373398
() => {
374399
core::iter::empty()
375400
};
376-
( $first:expr $(, $rest:expr )* $(,)*) => {
377-
core::iter::IntoIterator::into_iter($first)
401+
($first:expr $(, $rest:expr )* $(,)?) => {
402+
{
403+
let iter = core::iter::IntoIterator::into_iter($first);
378404
$(
379-
.chain(
380-
core::iter::IntoIterator::into_iter($rest)
381-
)
405+
let iter =
406+
core::iter::Iterator::chain(
407+
iter,
408+
core::iter::IntoIterator::into_iter($rest));
382409
)*
410+
iter
411+
}
383412
};
384413
}
385414

0 commit comments

Comments
 (0)