From a9bdbb2a447e645c9a95f2da8b96d148d15cfd5a Mon Sep 17 00:00:00 2001 From: Colin Woodbury Date: Tue, 24 Aug 2021 21:07:31 -0700 Subject: [PATCH 1/3] [iter] Checkpoint on `Cycle` --- src/iter.rs | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/iter.rs b/src/iter.rs index 4c26a8f..b4317ad 100644 --- a/src/iter.rs +++ b/src/iter.rs @@ -204,6 +204,16 @@ pub trait NonEmptyIterator { 1 + rest.count() } + /// Repeats a non-empty iterator endlessly. + /// + /// See also [`Iterator::cycle`]. + fn cycle(self) -> Cycle + where + Self: Sized + Clone, + { + Cycle::new(self) + } + /// Creates a non-empty iterator which gives the current iteration count as /// well as the next value. /// @@ -744,3 +754,37 @@ where self.iter.into_iter().copied() } } + +/// An iterator that repeats endlessly. +/// +/// See also [`std::iter::Cycle`]. +pub struct Cycle { + orig: I, + iter: I, +} + +impl Cycle { + pub fn new(iter: I) -> Self { + Self { + orig: iter.clone(), + iter, + } + } +} + +// impl NonEmptyIterator for Cycle +// where +// I: Clone + NonEmptyIterator, +// { +// type Item = T; + +// type Iter = std::iter::Cycle; + +// fn first(self) -> (Self::Item, Self::Iter) { +// todo!() +// } + +// fn next(&mut self) -> Option { +// todo!() +// } +// } From 3d2c3c22028d98791585c9fc172581a2974d3ad2 Mon Sep 17 00:00:00 2001 From: Colin Woodbury Date: Tue, 24 Aug 2021 21:36:33 -0700 Subject: [PATCH 2/3] [iter] Result of `first` only needs `IntoIterator` This accounts for cases like `Cycle`, where the result of `first` is still guaranteed to be non-empty! --- src/iter.rs | 48 ++++++++++++++++++++++++------------------------ src/set.rs | 8 ++++---- src/vector.rs | 4 ++-- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/iter.rs b/src/iter.rs index b4317ad..2ea7172 100644 --- a/src/iter.rs +++ b/src/iter.rs @@ -31,11 +31,11 @@ pub trait NonEmptyIterator { /// Each `NonEmptyIterator` knows about a possibly-empty variant of itself, /// likely from `std`. Critically, they share an `Item`. - type Iter: Iterator; + type IntoIter: IntoIterator; /// A `NonEmptyIterator` can, by consuming itself, reliably produce its /// first element, alongside its possibly-empty variant. - fn first(self) -> (Self::Item, Self::Iter); + fn first(self) -> (Self::Item, Self::IntoIter); /// Advances the iterator and returns the next value. /// @@ -201,7 +201,7 @@ pub trait NonEmptyIterator { // Differs from the implementation of `Iterator::count` to absolutely // ensure that `count` returns at least 1. let (_, rest) = self.first(); - 1 + rest.count() + 1 + rest.into_iter().count() } /// Repeats a non-empty iterator endlessly. @@ -460,14 +460,14 @@ where { type Item = U; - type Iter = std::iter::Map; + type IntoIter = std::iter::Map<::IntoIter, F>; - fn first(self) -> (Self::Item, Self::Iter) { + fn first(self) -> (Self::Item, Self::IntoIter) { let (i, iter) = self.iter.first(); let mut fun = self.f; // Reconstruct the `Map` we broke open. - (fun(i), iter.map(fun)) + (fun(i), iter.into_iter().map(fun)) } fn next(&mut self) -> Option { @@ -508,12 +508,12 @@ where { type Item = T; - type Iter = std::iter::Cloned; + type IntoIter = std::iter::Cloned<::IntoIter>; - fn first(self) -> (Self::Item, Self::Iter) { + fn first(self) -> (Self::Item, Self::IntoIter) { let (i, iter) = self.iter.first(); - (i.clone(), iter.cloned()) + (i.clone(), iter.into_iter().cloned()) } fn next(&mut self) -> Option { @@ -549,12 +549,12 @@ where { type Item = (usize, I::Item); - type Iter = std::iter::Enumerate; + type IntoIter = std::iter::Enumerate<::IntoIter>; - fn first(self) -> (Self::Item, Self::Iter) { + fn first(self) -> (Self::Item, Self::IntoIter) { let (head, rest) = self.iter.first(); - ((0, head), rest.enumerate()) + ((0, head), rest.into_iter().enumerate()) } fn next(&mut self) -> Option { @@ -592,15 +592,15 @@ where { type Item = I::Item; - type Iter = std::iter::Take; + type IntoIter = std::iter::Take<::IntoIter>; - fn first(self) -> (Self::Item, Self::Iter) { + fn first(self) -> (Self::Item, Self::IntoIter) { let (head, rest) = self.iter.first(); if self.n < 2 { - (head, rest.take(0)) + (head, rest.into_iter().take(0)) } else { - (head, rest.take(self.n - 1)) + (head, rest.into_iter().take(self.n - 1)) } } @@ -640,12 +640,12 @@ where { type Item = A::Item; - type Iter = std::iter::Chain; + type IntoIter = std::iter::Chain<::IntoIter, B>; - fn first(self) -> (Self::Item, Self::Iter) { + fn first(self) -> (Self::Item, Self::IntoIter) { let (head, a_rest) = self.a.first(); - (head, a_rest.chain(self.b)) + (head, a_rest.into_iter().chain(self.b)) } fn next(&mut self) -> Option { @@ -686,9 +686,9 @@ where { type Item = T; - type Iter = std::option::IntoIter; + type IntoIter = std::option::IntoIter; - fn first(self) -> (Self::Item, Self::Iter) { + fn first(self) -> (Self::Item, Self::IntoIter) { (self.once, None.into_iter()) } @@ -728,12 +728,12 @@ where { type Item = T; - type Iter = std::iter::Copied; + type IntoIter = std::iter::Copied<::IntoIter>; - fn first(self) -> (Self::Item, Self::Iter) { + fn first(self) -> (Self::Item, Self::IntoIter) { let (head, rest) = self.iter.first(); - (head.clone(), rest.copied()) + (head.clone(), rest.into_iter().copied()) } fn next(&mut self) -> Option { diff --git a/src/set.rs b/src/set.rs index a6e0a92..d0c5551 100644 --- a/src/set.rs +++ b/src/set.rs @@ -464,9 +464,9 @@ impl<'a, T> IntoIterator for &'a NESet { impl<'a, T> NonEmptyIterator for Iter<'a, T> { type Item = &'a T; - type Iter = Skip, std::collections::hash_set::Iter<'a, T>>>; + type IntoIter = Skip, std::collections::hash_set::Iter<'a, T>>>; - fn first(self) -> (Self::Item, Self::Iter) { + fn first(self) -> (Self::Item, Self::IntoIter) { (self.head, self.iter.skip(1)) } @@ -513,7 +513,7 @@ where { type Item = &'a T; - type Iter = std::collections::hash_set::Union<'a, T, S>; + type IntoIter = std::collections::hash_set::Union<'a, T, S>; fn next(&mut self) -> Option { match self.orig_iter.next() { @@ -527,7 +527,7 @@ where } } - fn first(self) -> (Self::Item, Self::Iter) { + fn first(self) -> (Self::Item, Self::IntoIter) { (&self.orig.head, self.orig.tail.union(&self.other.tail)) } diff --git a/src/vector.rs b/src/vector.rs index 3c92a58..06d25b8 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -822,13 +822,13 @@ pub struct Iter<'a, T: 'a> { impl<'a, T> NonEmptyIterator for Iter<'a, T> { type Item = &'a T; - type Iter = Skip, std::slice::Iter<'a, T>>>; + type IntoIter = Skip, std::slice::Iter<'a, T>>>; fn next(&mut self) -> Option { self.iter.next() } - fn first(self) -> (Self::Item, Self::Iter) { + fn first(self) -> (Self::Item, Self::IntoIter) { (self.head, self.iter.skip(1)) } } From 66816d7270085086aeddf235752414d586bfd7db Mon Sep 17 00:00:00 2001 From: Colin Woodbury Date: Wed, 25 Aug 2021 20:47:23 -0700 Subject: [PATCH 3/3] [iter] First pass at real `Cycle` instances --- src/iter.rs | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/src/iter.rs b/src/iter.rs index 2ea7172..fb54567 100644 --- a/src/iter.rs +++ b/src/iter.rs @@ -764,7 +764,7 @@ pub struct Cycle { } impl Cycle { - pub fn new(iter: I) -> Self { + fn new(iter: I) -> Self { Self { orig: iter.clone(), iter, @@ -772,19 +772,34 @@ impl Cycle { } } -// impl NonEmptyIterator for Cycle -// where -// I: Clone + NonEmptyIterator, -// { -// type Item = T; +impl NonEmptyIterator for Cycle +where + I: NonEmptyIterator, + Self: IntoIterator, +{ + type Item = T; -// type Iter = std::iter::Cycle; + type IntoIter = Self; -// fn first(self) -> (Self::Item, Self::Iter) { -// todo!() -// } + fn first(self) -> (Self::Item, Self::IntoIter) { + todo!() + } + + fn next(&mut self) -> Option { + todo!() + } +} -// fn next(&mut self) -> Option { -// todo!() -// } -// } +impl IntoIterator for Cycle +where + I: IntoIterator, + J: Clone + Iterator, +{ + type Item = T; + + type IntoIter = std::iter::Cycle; + + fn into_iter(self) -> Self::IntoIter { + todo!() + } +}