File tree Expand file tree Collapse file tree 2 files changed +51
-4
lines changed Expand file tree Collapse file tree 2 files changed +51
-4
lines changed Original file line number Diff line number Diff line change @@ -99,3 +99,50 @@ fn bench_zip_add(b: &mut Bencher) {
9999 add_zip ( & source, & mut dst)
100100 } ) ;
101101}
102+
103+ /// `Iterator::for_each` implemented as a plain loop.
104+ fn for_each_loop < I , F > ( iter : I , mut f : F ) where
105+ I : Iterator , F : FnMut ( I :: Item )
106+ {
107+ for item in iter {
108+ f ( item) ;
109+ }
110+ }
111+
112+ /// `Iterator::for_each` implemented with `fold` for internal iteration.
113+ /// (except when `by_ref()` effectively disables that optimization.)
114+ fn for_each_fold < I , F > ( iter : I , mut f : F ) where
115+ I : Iterator , F : FnMut ( I :: Item )
116+ {
117+ iter. fold ( ( ) , move |( ) , item| f ( item) ) ;
118+ }
119+
120+ #[ bench]
121+ fn bench_for_each_chain_loop ( b : & mut Bencher ) {
122+ b. iter ( || {
123+ let mut acc = 0 ;
124+ let iter = ( 0i64 ..1000000 ) . chain ( 0 ..1000000 ) . map ( black_box) ;
125+ for_each_loop ( iter, |x| acc += x) ;
126+ acc
127+ } ) ;
128+ }
129+
130+ #[ bench]
131+ fn bench_for_each_chain_fold ( b : & mut Bencher ) {
132+ b. iter ( || {
133+ let mut acc = 0 ;
134+ let iter = ( 0i64 ..1000000 ) . chain ( 0 ..1000000 ) . map ( black_box) ;
135+ for_each_fold ( iter, |x| acc += x) ;
136+ acc
137+ } ) ;
138+ }
139+
140+ #[ bench]
141+ fn bench_for_each_chain_ref_fold ( b : & mut Bencher ) {
142+ b. iter ( || {
143+ let mut acc = 0 ;
144+ let mut iter = ( 0i64 ..1000000 ) . chain ( 0 ..1000000 ) . map ( black_box) ;
145+ for_each_fold ( iter. by_ref ( ) , |x| acc += x) ;
146+ acc
147+ } ) ;
148+ }
Original file line number Diff line number Diff line change @@ -487,7 +487,9 @@ pub trait Iterator {
487487 /// This is equivalent to using a [`for`] loop on the iterator, although
488488 /// `break` and `continue` are not possible from a closure. It's generally
489489 /// more idiomatic to use a `for` loop, but `for_each` may be more legible
490- /// when processing items at the end of longer iterator chains.
490+ /// when processing items at the end of longer iterator chains. In some
491+ /// cases `for_each` may also be faster than a loop, because it will use
492+ /// internal iteration on adaptors like `Chain`.
491493 ///
492494 /// [`for`]: ../../book/first-edition/loops.html#for
493495 ///
@@ -523,9 +525,7 @@ pub trait Iterator {
523525 fn for_each < F > ( self , mut f : F ) where
524526 Self : Sized , F : FnMut ( Self :: Item ) ,
525527 {
526- for item in self {
527- f ( item) ;
528- }
528+ self . fold ( ( ) , move |( ) , item| f ( item) ) ;
529529 }
530530
531531 /// Creates an iterator which uses a closure to determine if an element
You can’t perform that action at this time.
0 commit comments