From 4decb2cdcf882bb4be5613ee63fd6472d135b44e Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 21 Oct 2020 09:59:42 -0700 Subject: [PATCH] impl IntoIterator for (A, B) as Zip This makes it a little easier to `zip` iterators: ```rust for (x, y) in (xs, ys) {} // vs. for (x, y) in xs.into_iter().zip(ys) {} ``` You can iterate `(&mut xs, &ys)` for the conventional `iter_mut()` and `iter()`, respectively. This can also support arbitrary nesting, where it's easier to see the item layout than with arbitrary `zip` chains: ```rust for ((x, y), z) in ((xs, ys), zs) {} for (x, (y, z)) in (xs, (ys, zs)) {} // vs. for ((x, y), z) in xs.into_iter().zip(ys).zip(xz) {} for (x, (y, z)) in xs.into_iter().zip((ys.into_iter().zip(xz)) {} ``` Only tuple pairs are implemented for now. It's possible to implement longer tuples, but that would require a new iterator type to produce those tuple items. See itertools' [`Zip`] and rayon's [`MultiZip`] for prior art there. [`Zip`]: https://docs.rs/itertools/0.9.0/itertools/structs/struct.Zip.html [`MultiZip`]: https://docs.rs/rayon/1.4.1/rayon/iter/struct.MultiZip.html See also rust-lang/rfcs#870 and rust-lang/rfcs#930. --- library/core/src/tuple.rs | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs index 9f8a3a1de4201..7dc7bc59f6f51 100644 --- a/library/core/src/tuple.rs +++ b/library/core/src/tuple.rs @@ -2,6 +2,7 @@ use crate::cmp::Ordering::*; use crate::cmp::*; +use crate::iter::{IntoIterator, Zip}; // macro for implementing n-ary tuple functions and operations macro_rules! tuple_impls { @@ -211,3 +212,39 @@ tuple_impls! { (11) -> L } } + +/// Converts a pair of `IntoIterator` values into a single iterator of pairs +/// +/// This works like an implicit [`zip`] in any context that accepts `IntoIterator` +/// values, like [`chain`], [`flat_map`], and especially `for` loops. +/// +/// ``` +/// let xs = [1, 2, 3]; +/// let ys = [4, 5, 6]; +/// for (x, y) in (&xs, &ys) { +/// println!("x:{}, y:{}", x, y); +/// } +/// +/// // Nested zips are also possible: +/// let zs = [7, 8, 9]; +/// for ((x, y), z) in ((&xs, &ys), &zs) { +/// println!("x:{}, y:{}, z:{}", x, y, z); +/// } +/// ``` +/// +/// [`chain`]: Iterator::chain +/// [`flat_map`]: Iterator::flat_map +/// [`zip`]: Iterator::zip +#[stable(feature = "pair_into_iter", since = "1.49.0")] +impl IntoIterator for (A, B) +where + A: IntoIterator, + B: IntoIterator, +{ + type IntoIter = Zip; + type Item = (A::Item, B::Item); + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter().zip(self.1) + } +}