From 50568449cdf7c374332f5386dce4185eb594de15 Mon Sep 17 00:00:00 2001 From: Sebastian Widua Date: Sun, 30 May 2021 18:44:37 +0200 Subject: [PATCH 1/5] Implement Extend<(A, B)> for (impl Extend, impl Extend) --- library/core/src/iter/traits/collect.rs | 40 +++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index e2a407509b10d..f9ccb35d03953 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -358,3 +358,43 @@ impl Extend<()> for () { } fn extend_one(&mut self, _item: ()) {} } + +#[stable(feature = "extend_for_tuple", since = "1.54.0")] +impl Extend<(A, B)> for (ExtendA, ExtendB) +where + ExtendA: Extend, + ExtendB: Extend, +{ + fn extend>(&mut self, into_iter: T) { + let (a, b) = self; + let iter = into_iter.into_iter(); + + fn extend<'a, A, B>( + a: &'a mut impl Extend, + b: &'a mut impl Extend, + ) -> impl FnMut((), (A, B)) + 'a { + move |(), (t, u)| { + a.extend_one(t); + b.extend_one(u); + } + } + + let (lower_bound, _) = iter.size_hint(); + if lower_bound > 0 { + a.extend_reserve(lower_bound); + b.extend_reserve(lower_bound); + } + + iter.fold((), extend(a, b)); + } + + fn extend_one(&mut self, item: (A, B)) { + self.0.extend_one(item.0); + self.1.extend_one(item.1); + } + + fn extend_reserve(&mut self, additional: usize) { + self.0.extend_reserve(additional); + self.1.extend_reserve(additional); + } +} From b5e92756b305c6ec4bdd42feddd013333eb69d63 Mon Sep 17 00:00:00 2001 From: Sebastian Widua Date: Sun, 30 May 2021 18:49:31 +0200 Subject: [PATCH 2/5] Rewrite Iterator::unzip in terms of (A, B)::extend --- library/core/src/iter/traits/iterator.rs | 25 +++--------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 96b924f6e2ad4..18c9757173ada 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -2819,28 +2819,9 @@ pub trait Iterator { FromB: Default + Extend, Self: Sized + Iterator, { - fn extend<'a, A, B>( - ts: &'a mut impl Extend, - us: &'a mut impl Extend, - ) -> impl FnMut((), (A, B)) + 'a { - move |(), (t, u)| { - ts.extend_one(t); - us.extend_one(u); - } - } - - let mut ts: FromA = Default::default(); - let mut us: FromB = Default::default(); - - let (lower_bound, _) = self.size_hint(); - if lower_bound > 0 { - ts.extend_reserve(lower_bound); - us.extend_reserve(lower_bound); - } - - self.fold((), extend(&mut ts, &mut us)); - - (ts, us) + let mut unzipped: (FromA, FromB) = Default::default(); + unzipped.extend(self); + unzipped } /// Creates an iterator which copies all of its elements. From 96b7d07a477fc118b045e4ed49086dcf6975b962 Mon Sep 17 00:00:00 2001 From: Sebastian Widua Date: Mon, 14 Jun 2021 17:01:40 +0200 Subject: [PATCH 3/5] Mention nested unzip in its documentation --- library/core/src/iter/traits/iterator.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index a7e914526f408..97d6d470b3685 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -2811,6 +2811,14 @@ pub trait Iterator { /// /// assert_eq!(left, [1, 3]); /// assert_eq!(right, [2, 4]); + /// + /// // you can also unzip multiple nested tuples at once + /// let a = [(1, (2, 3)), (4, (5, 6))]; + /// + /// let (x, (y, z)): (Vec<_>, (Vec<_>, Vec<_>)) = a.iter().cloned().unzip(); + /// assert_eq!(x, [1, 4]); + /// assert_eq!(y, [2, 5]); + /// assert_eq!(z, [3, 6]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn unzip(self) -> (FromA, FromB) From 7b907597332e430653673531e2bc29b1ae286f3c Mon Sep 17 00:00:00 2001 From: Sebastian Widua Date: Sun, 20 Jun 2021 11:19:55 +0200 Subject: [PATCH 4/5] Add documentation/example to Extend impl --- library/core/src/iter/traits/collect.rs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index f9ccb35d03953..033b6084f1bc2 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -359,12 +359,30 @@ impl Extend<()> for () { fn extend_one(&mut self, _item: ()) {} } -#[stable(feature = "extend_for_tuple", since = "1.54.0")] +#[stable(feature = "extend_for_tuple", since = "1.55.0")] impl Extend<(A, B)> for (ExtendA, ExtendB) where ExtendA: Extend, ExtendB: Extend, { + /// Allows to `extend` a tuple of collections that also implement `Extend`. + /// + /// See also: [`Iterator::unzip`] + /// + /// # Examples + /// ``` + /// let mut tuple = (vec![0], vec![1]); + /// tuple.extend(vec![(2, 3), (4, 5), (6, 7)]); + /// assert_eq!(tuple.0, vec![0, 2, 4, 6]); + /// assert_eq!(tuple.1, vec![1, 3, 5, 7]); + /// + /// // also allows for arbitrarily nested tuples + /// let mut nested_tuple = (vec![(1, -1)], vec![(2, -2)]); + /// nested_tuple.extend(vec![((3, -3), (4, -4)), ((5, -5), (6, -6))]); + /// + /// assert_eq!(nested_tuple.0, vec![(1, -1), (3, -3), (5, -5)]); + /// assert_eq!(nested_tuple.1, vec![(2, -2), (4, -4), (6, -6)]); + /// ``` fn extend>(&mut self, into_iter: T) { let (a, b) = self; let iter = into_iter.into_iter(); From 3d0c5d09d33d74a508965799fcde6e8147cee721 Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Tue, 3 Aug 2021 12:12:14 -0700 Subject: [PATCH 5/5] Update library/core/src/iter/traits/collect.rs Co-authored-by: teor --- library/core/src/iter/traits/collect.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index 033b6084f1bc2..b36ae0e20c258 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -359,7 +359,7 @@ impl Extend<()> for () { fn extend_one(&mut self, _item: ()) {} } -#[stable(feature = "extend_for_tuple", since = "1.55.0")] +#[stable(feature = "extend_for_tuple", since = "1.56.0")] impl Extend<(A, B)> for (ExtendA, ExtendB) where ExtendA: Extend,