mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-25 21:34:18 +00:00
Use fold
to implement Iterator::for_each
The benefit of using internal iteration is shown in new benchmarks: test iter::bench_for_each_chain_fold ... bench: 635,110 ns/iter (+/- 5,135) test iter::bench_for_each_chain_loop ... bench: 2,249,983 ns/iter (+/- 42,001) test iter::bench_for_each_chain_ref_fold ... bench: 2,248,061 ns/iter (+/- 51,940)
This commit is contained in:
parent
b4038977a3
commit
4a8ddac99e
@ -99,3 +99,50 @@ fn bench_zip_add(b: &mut Bencher) {
|
|||||||
add_zip(&source, &mut dst)
|
add_zip(&source, &mut dst)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `Iterator::for_each` implemented as a plain loop.
|
||||||
|
fn for_each_loop<I, F>(iter: I, mut f: F) where
|
||||||
|
I: Iterator, F: FnMut(I::Item)
|
||||||
|
{
|
||||||
|
for item in iter {
|
||||||
|
f(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Iterator::for_each` implemented with `fold` for internal iteration.
|
||||||
|
/// (except when `by_ref()` effectively disables that optimization.)
|
||||||
|
fn for_each_fold<I, F>(iter: I, mut f: F) where
|
||||||
|
I: Iterator, F: FnMut(I::Item)
|
||||||
|
{
|
||||||
|
iter.fold((), move |(), item| f(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn bench_for_each_chain_loop(b: &mut Bencher) {
|
||||||
|
b.iter(|| {
|
||||||
|
let mut acc = 0;
|
||||||
|
let iter = (0i64..1000000).chain(0..1000000).map(black_box);
|
||||||
|
for_each_loop(iter, |x| acc += x);
|
||||||
|
acc
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn bench_for_each_chain_fold(b: &mut Bencher) {
|
||||||
|
b.iter(|| {
|
||||||
|
let mut acc = 0;
|
||||||
|
let iter = (0i64..1000000).chain(0..1000000).map(black_box);
|
||||||
|
for_each_fold(iter, |x| acc += x);
|
||||||
|
acc
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn bench_for_each_chain_ref_fold(b: &mut Bencher) {
|
||||||
|
b.iter(|| {
|
||||||
|
let mut acc = 0;
|
||||||
|
let mut iter = (0i64..1000000).chain(0..1000000).map(black_box);
|
||||||
|
for_each_fold(iter.by_ref(), |x| acc += x);
|
||||||
|
acc
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -487,7 +487,9 @@ pub trait Iterator {
|
|||||||
/// This is equivalent to using a [`for`] loop on the iterator, although
|
/// This is equivalent to using a [`for`] loop on the iterator, although
|
||||||
/// `break` and `continue` are not possible from a closure. It's generally
|
/// `break` and `continue` are not possible from a closure. It's generally
|
||||||
/// more idiomatic to use a `for` loop, but `for_each` may be more legible
|
/// more idiomatic to use a `for` loop, but `for_each` may be more legible
|
||||||
/// when processing items at the end of longer iterator chains.
|
/// when processing items at the end of longer iterator chains. In some
|
||||||
|
/// cases `for_each` may also be faster than a loop, because it will use
|
||||||
|
/// internal iteration on adaptors like `Chain`.
|
||||||
///
|
///
|
||||||
/// [`for`]: ../../book/first-edition/loops.html#for
|
/// [`for`]: ../../book/first-edition/loops.html#for
|
||||||
///
|
///
|
||||||
@ -523,9 +525,7 @@ pub trait Iterator {
|
|||||||
fn for_each<F>(self, mut f: F) where
|
fn for_each<F>(self, mut f: F) where
|
||||||
Self: Sized, F: FnMut(Self::Item),
|
Self: Sized, F: FnMut(Self::Item),
|
||||||
{
|
{
|
||||||
for item in self {
|
self.fold((), move |(), item| f(item));
|
||||||
f(item);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates an iterator which uses a closure to determine if an element
|
/// Creates an iterator which uses a closure to determine if an element
|
||||||
|
Loading…
Reference in New Issue
Block a user