Skip to content

Commit 3e0cd6a

Browse files
committed
Override <RangeInclusive as Iterator>::try_(r)fold
1 parent 5182cc1 commit 3e0cd6a

File tree

2 files changed

+77
-1
lines changed

2 files changed

+77
-1
lines changed

src/libcore/benches/iter.rs

+36
Original file line numberDiff line numberDiff line change
@@ -310,3 +310,39 @@ fn bench_skip_then_zip(b: &mut Bencher) {
310310
assert_eq!(s, 2009900);
311311
});
312312
}
313+
314+
#[bench]
315+
fn bench_triples_inclusive_range(b: &mut Bencher) {
316+
// Example from #45222
317+
b.iter(|| {
318+
(1..)
319+
.flat_map(|z| {
320+
(1u32..=z).flat_map(move |x| {
321+
(x..=z)
322+
.filter(move |&y| x.pow(2) + y.pow(2) == z.pow(2))
323+
.map(move |y| (x, y, z))
324+
})
325+
})
326+
.take(20)
327+
.map(|(x, y, z)| x + y + z)
328+
.sum::<u32>()
329+
})
330+
}
331+
332+
#[bench]
333+
fn bench_triples_range(b: &mut Bencher) {
334+
// Example from #45222
335+
b.iter(|| {
336+
(1..)
337+
.flat_map(|z| {
338+
(1u32..z+1).flat_map(move |x| {
339+
(x..z+1)
340+
.filter(move |&y| x.pow(2) + y.pow(2) == z.pow(2))
341+
.map(move |y| (x, y, z))
342+
})
343+
})
344+
.take(20)
345+
.map(|(x, y, z)| x + y + z)
346+
.sum::<u32>()
347+
})
348+
}

src/libcore/iter/range.rs

+41-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use convert::TryFrom;
1212
use mem;
13-
use ops::{self, Add, Sub};
13+
use ops::{self, Add, Sub, Try};
1414
use usize;
1515

1616
use super::{FusedIterator, TrustedLen};
@@ -406,6 +406,26 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
406406
fn max(mut self) -> Option<A> {
407407
self.next_back()
408408
}
409+
410+
#[inline]
411+
fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R where
412+
Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B>
413+
{
414+
let mut accum = init;
415+
416+
self.compute_is_empty();
417+
if self.is_empty.unwrap_or_default() {
418+
return Try::from_ok(accum);
419+
}
420+
421+
while self.start < self.end {
422+
let n = self.start.add_one();
423+
accum = f(accum, mem::replace(&mut self.start, n))?;
424+
}
425+
426+
self.is_empty = Some(true);
427+
f(accum, self.start.clone())
428+
}
409429
}
410430

411431
#[stable(feature = "inclusive_range", since = "1.26.0")]
@@ -425,6 +445,26 @@ impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> {
425445
self.end.clone()
426446
})
427447
}
448+
449+
#[inline]
450+
fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R where
451+
Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B>
452+
{
453+
let mut accum = init;
454+
455+
self.compute_is_empty();
456+
if self.is_empty.unwrap_or_default() {
457+
return Try::from_ok(accum);
458+
}
459+
460+
while self.start < self.end {
461+
let n = self.end.sub_one();
462+
accum = f(accum, mem::replace(&mut self.end, n))?;
463+
}
464+
465+
self.is_empty = Some(true);
466+
f(accum, self.end.clone())
467+
}
428468
}
429469

430470
#[stable(feature = "fused", since = "1.26.0")]

0 commit comments

Comments
 (0)