@@ -43,6 +43,8 @@ much easier to implement.
43
43
#[ cfg( not( stage0) ) ] use cmp:: Ord ;
44
44
#[ cfg( not( stage0) ) ] use option:: { Option , Some , None } ;
45
45
#[ cfg( not( stage0) ) ] use vec:: OwnedVector ;
46
+ #[ cfg( not( stage0) ) ] use num:: { One , Zero } ;
47
+ #[ cfg( not( stage0) ) ] use ops:: { Add , Mul } ;
46
48
47
49
#[ cfg( stage0) ]
48
50
pub trait Times {
@@ -212,6 +214,81 @@ pub fn min<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
212
214
result
213
215
}
214
216
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
+
215
292
#[ cfg( test) ]
216
293
mod tests {
217
294
use super :: * ;
@@ -254,4 +331,33 @@ mod tests {
254
331
let xs = ~[ 8 , 2 , 3 , 1 , -5 , 9 , 11 , 15 ] ;
255
332
assert_eq ! ( min( |f| xs. each( f) ) . unwrap( ) , & -5 ) ;
256
333
}
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
+ }
257
363
}
0 commit comments