Skip to content

Commit 09bf401

Browse files
committed
auto merge of #6544 : thestinger/rust/new_iter, r=nikomatsakis
2 parents 17970a9 + 08ef229 commit 09bf401

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed

src/libcore/iter.rs

+106
Original file line numberDiff line numberDiff line change
@@ -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)]
4850
pub 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)]
216293
mod 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(0i, |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

Comments
 (0)