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
+ });
+}
/// This is equivalent to using a [`for`] loop on the iterator, although
/// `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
- /// 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
///
fn for_each<F>(self, mut f: F) where
Self: Sized, F: FnMut(Self::Item),
{
- for item in self {
- f(item);
- }
+ self.fold((), move |(), item| f(item));
}
/// Creates an iterator which uses a closure to determine if an element