Skip to content

Commit 0ba7fd7

Browse files
Philippe-Choletjswrenn
authored andcommitted
Make CoalesceBy lazy
Similar to what is done by `core::iter::Peekable`, a nested option is now used.
1 parent 5d925d2 commit 0ba7fd7

File tree

1 file changed

+34
-23
lines changed

1 file changed

+34
-23
lines changed

src/adaptors/coalesce.rs

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ where
1010
C: CountItem<I::Item>,
1111
{
1212
iter: I,
13-
last: Option<C::CItem>,
13+
last: Option<Option<C::CItem>>,
1414
f: F,
1515
}
1616

@@ -45,36 +45,47 @@ where
4545
type Item = C::CItem;
4646

4747
fn next(&mut self) -> Option<Self::Item> {
48+
let Self { iter, last, f } = self;
4849
// this fuses the iterator
49-
let last = self.last.take()?;
50+
let init = match last {
51+
Some(elt) => elt.take(),
52+
None => {
53+
*last = Some(None);
54+
iter.next().map(C::new)
55+
}
56+
}?;
5057

51-
let self_last = &mut self.last;
52-
let self_f = &mut self.f;
5358
Some(
54-
self.iter
55-
.try_fold(last, |last, next| match self_f.coalesce_pair(last, next) {
56-
Ok(joined) => Ok(joined),
57-
Err((last_, next_)) => {
58-
*self_last = Some(next_);
59-
Err(last_)
60-
}
61-
})
62-
.unwrap_or_else(|x| x),
59+
iter.try_fold(init, |accum, next| match f.coalesce_pair(accum, next) {
60+
Ok(joined) => Ok(joined),
61+
Err((last_, next_)) => {
62+
*last = Some(Some(next_));
63+
Err(last_)
64+
}
65+
})
66+
.unwrap_or_else(|x| x),
6367
)
6468
}
6569

6670
fn size_hint(&self) -> (usize, Option<usize>) {
67-
let (low, hi) = size_hint::add_scalar(self.iter.size_hint(), self.last.is_some() as usize);
71+
let (low, hi) = size_hint::add_scalar(
72+
self.iter.size_hint(),
73+
matches!(self.last, Some(Some(_))) as usize,
74+
);
6875
((low > 0) as usize, hi)
6976
}
7077

7178
fn fold<Acc, FnAcc>(self, acc: Acc, mut fn_acc: FnAcc) -> Acc
7279
where
7380
FnAcc: FnMut(Acc, Self::Item) -> Acc,
7481
{
75-
if let Some(last) = self.last {
76-
let mut f = self.f;
77-
let (last, acc) = self.iter.fold((last, acc), |(last, acc), elt| {
82+
let Self {
83+
mut iter,
84+
last,
85+
mut f,
86+
} = self;
87+
if let Some(last) = last.unwrap_or_else(|| iter.next().map(C::new)) {
88+
let (last, acc) = iter.fold((last, acc), |(last, acc), elt| {
7889
match f.coalesce_pair(last, elt) {
7990
Ok(joined) => (joined, acc),
8091
Err((last_, next_)) => (next_, fn_acc(acc, last_)),
@@ -135,12 +146,12 @@ where
135146
}
136147

137148
/// Create a new `Coalesce`.
138-
pub fn coalesce<I, F>(mut iter: I, f: F) -> Coalesce<I, F>
149+
pub fn coalesce<I, F>(iter: I, f: F) -> Coalesce<I, F>
139150
where
140151
I: Iterator,
141152
{
142153
Coalesce {
143-
last: iter.next(),
154+
last: None,
144155
iter,
145156
f,
146157
}
@@ -192,12 +203,12 @@ impl<T, F: FnMut(&T, &T) -> bool> DedupPredicate<T> for F {
192203
}
193204

194205
/// Create a new `DedupBy`.
195-
pub fn dedup_by<I, Pred>(mut iter: I, dedup_pred: Pred) -> DedupBy<I, Pred>
206+
pub fn dedup_by<I, Pred>(iter: I, dedup_pred: Pred) -> DedupBy<I, Pred>
196207
where
197208
I: Iterator,
198209
{
199210
DedupBy {
200-
last: iter.next(),
211+
last: None,
201212
iter,
202213
f: DedupPred2CoalescePred(dedup_pred),
203214
}
@@ -251,12 +262,12 @@ where
251262
pub type DedupWithCount<I> = DedupByWithCount<I, DedupEq>;
252263

253264
/// Create a new `DedupByWithCount`.
254-
pub fn dedup_by_with_count<I, Pred>(mut iter: I, dedup_pred: Pred) -> DedupByWithCount<I, Pred>
265+
pub fn dedup_by_with_count<I, Pred>(iter: I, dedup_pred: Pred) -> DedupByWithCount<I, Pred>
255266
where
256267
I: Iterator,
257268
{
258269
DedupByWithCount {
259-
last: iter.next().map(WithCount::new),
270+
last: None,
260271
iter,
261272
f: DedupPredWithCount2CoalescePred(dedup_pred),
262273
}

0 commit comments

Comments
 (0)