@@ -43,6 +43,8 @@ much easier to implement.
4343#[ cfg( not( stage0) ) ] use cmp:: Ord ;
4444#[ cfg( not( stage0) ) ] use option:: { Option , Some , None } ;
4545#[ cfg( not( stage0) ) ] use vec:: OwnedVector ;
46+ #[ cfg( not( stage0) ) ] use num:: { One , Zero } ;
47+ #[ cfg( not( stage0) ) ] use ops:: { Add , Mul } ;
4648
4749#[ cfg( stage0) ]
4850pub trait Times {
@@ -212,6 +214,81 @@ pub fn min<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
212214 result
213215}
214216
217+ /**
218+ * Reduce an iterator to an accumulated value.
219+ *
220+ * # Example:
221+ *
222+ * ~~~~
223+ * assert_eq!(fold(0i, |f| int::range(1, 5, f), |a, x| *a += x), 10);
224+ * ~~~~
225+ */
226+ #[ cfg( not( stage0) ) ]
227+ #[ inline]
228+ pub fn fold < T , U > ( start : T , iter : & fn ( f : & fn ( U ) -> bool ) -> bool , f : & fn ( & mut T , U ) ) -> T {
229+ let mut result = start;
230+ for iter |x| {
231+ f( & mut result, x) ;
232+ }
233+ result
234+ }
235+
236+ /**
237+ * Reduce an iterator to an accumulated value.
238+ *
239+ * `fold_ref` is usable in some generic functions where `fold` is too lenient to type-check, but it
240+ * forces the iterator to yield borrowed pointers.
241+ *
242+ * # Example:
243+ *
244+ * ~~~~
245+ * fn product<T: One + Mul<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T {
246+ * fold_ref(One::one::<T>(), iter, |a, x| *a = a.mul(x))
247+ * }
248+ * ~~~~
249+ */
250+ #[ cfg( not( stage0) ) ]
251+ #[ inline]
252+ pub fn fold_ref < T , U > ( start : T , iter : & fn ( f : & fn ( & U ) -> bool ) -> bool , f : & fn ( & mut T , & U ) ) -> T {
253+ let mut result = start;
254+ for iter |x| {
255+ f( & mut result, x) ;
256+ }
257+ result
258+ }
259+
260+ /**
261+ * Return the sum of the items yielding by an iterator.
262+ *
263+ * # Example:
264+ *
265+ * ~~~~
266+ * let xs: ~[int] = ~[1, 2, 3, 4];
267+ * assert_eq!(do sum |f| { xs.each(f) }, 10);
268+ * ~~~~
269+ */
270+ #[ cfg( not( stage0) ) ]
271+ #[ inline( always) ]
272+ pub fn sum < T : Zero + Add < T , T > > ( iter : & fn ( f : & fn ( & T ) -> bool ) -> bool ) -> T {
273+ fold_ref ( Zero :: zero :: < T > ( ) , iter, |a, x| * a = a. add ( x) )
274+ }
275+
276+ /**
277+ * Return the product of the items yielded by an iterator.
278+ *
279+ * # Example:
280+ *
281+ * ~~~~
282+ * let xs: ~[int] = ~[1, 2, 3, 4];
283+ * assert_eq!(do product |f| { xs.each(f) }, 24);
284+ * ~~~~
285+ */
286+ #[ cfg( not( stage0) ) ]
287+ #[ inline( always) ]
288+ pub fn product < T : One + Mul < T , T > > ( iter : & fn ( f : & fn ( & T ) -> bool ) -> bool ) -> T {
289+ fold_ref ( One :: one :: < T > ( ) , iter, |a, x| * a = a. mul ( x) )
290+ }
291+
215292#[ cfg( test) ]
216293mod tests {
217294 use super :: * ;
@@ -254,4 +331,33 @@ mod tests {
254331 let xs = ~[ 8 , 2 , 3 , 1 , -5 , 9 , 11 , 15 ] ;
255332 assert_eq ! ( min( |f| xs. each( f) ) . unwrap( ) , & -5 ) ;
256333 }
334+
335+ #[ test]
336+ fn test_fold ( ) {
337+ assert_eq ! ( fold( 0 i, |f| int:: range( 1 , 5 , f) , |a, x| * a += x) , 10 ) ;
338+ }
339+
340+ #[ test]
341+ fn test_sum ( ) {
342+ let xs: ~[ int ] = ~[ 1 , 2 , 3 , 4 ] ;
343+ assert_eq ! ( do sum |f| { xs. each( f) } , 10 ) ;
344+ }
345+
346+ #[ test]
347+ fn test_empty_sum ( ) {
348+ let xs: ~[ int ] = ~[ ] ;
349+ assert_eq ! ( do sum |f| { xs. each( f) } , 0 ) ;
350+ }
351+
352+ #[ test]
353+ fn test_product ( ) {
354+ let xs: ~[ int ] = ~[ 1 , 2 , 3 , 4 ] ;
355+ assert_eq ! ( do product |f| { xs. each( f) } , 24 ) ;
356+ }
357+
358+ #[ test]
359+ fn test_empty_product ( ) {
360+ let xs: ~[ int ] = ~[ ] ;
361+ assert_eq ! ( do product |f| { xs. each( f) } , 1 ) ;
362+ }
257363}
0 commit comments