diff options
| author | Daniel Micay <danielmicay@gmail.com> | 2013-05-16 19:29:53 -0400 |
|---|---|---|
| committer | Daniel Micay <danielmicay@gmail.com> | 2013-05-16 21:51:31 -0400 |
| commit | 08ef229a65cd7b8de27a5844eee3dce8c69aa846 (patch) | |
| tree | 86d5c1ed684be5098988a9c5868d0c406d9c11f4 | |
| parent | 00eef96a007a817533e78860e97b251258177d5f (diff) | |
| download | rust-08ef229a65cd7b8de27a5844eee3dce8c69aa846.tar.gz rust-08ef229a65cd7b8de27a5844eee3dce8c69aa846.zip | |
iter: add fold, sum and product
| -rw-r--r-- | src/libcore/iter.rs | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index cfc9afb737c..ae4af3812d2 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -43,6 +43,8 @@ much easier to implement. #[cfg(not(stage0))] use cmp::Ord; #[cfg(not(stage0))] use option::{Option, Some, None}; #[cfg(not(stage0))] use vec::OwnedVector; +#[cfg(not(stage0))] use num::{One, Zero}; +#[cfg(not(stage0))] use ops::{Add, Mul}; #[cfg(stage0)] pub trait Times { @@ -212,6 +214,81 @@ pub fn min<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> { result } +/** + * Reduce an iterator to an accumulated value. + * + * # Example: + * + * ~~~~ + * assert_eq!(fold(0i, |f| int::range(1, 5, f), |a, x| *a += x), 10); + * ~~~~ + */ +#[cfg(not(stage0))] +#[inline] +pub fn fold<T, U>(start: T, iter: &fn(f: &fn(U) -> bool) -> bool, f: &fn(&mut T, U)) -> T { + let mut result = start; + for iter |x| { + f(&mut result, x); + } + result +} + +/** + * Reduce an iterator to an accumulated value. + * + * `fold_ref` is usable in some generic functions where `fold` is too lenient to type-check, but it + * forces the iterator to yield borrowed pointers. + * + * # Example: + * + * ~~~~ + * fn product<T: One + Mul<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T { + * fold_ref(One::one::<T>(), iter, |a, x| *a = a.mul(x)) + * } + * ~~~~ + */ +#[cfg(not(stage0))] +#[inline] +pub fn fold_ref<T, U>(start: T, iter: &fn(f: &fn(&U) -> bool) -> bool, f: &fn(&mut T, &U)) -> T { + let mut result = start; + for iter |x| { + f(&mut result, x); + } + result +} + +/** + * Return the sum of the items yielding by an iterator. + * + * # Example: + * + * ~~~~ + * let xs: ~[int] = ~[1, 2, 3, 4]; + * assert_eq!(do sum |f| { xs.each(f) }, 10); + * ~~~~ + */ +#[cfg(not(stage0))] +#[inline(always)] +pub fn sum<T: Zero + Add<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T { + fold_ref(Zero::zero::<T>(), iter, |a, x| *a = a.add(x)) +} + +/** + * Return the product of the items yielded by an iterator. + * + * # Example: + * + * ~~~~ + * let xs: ~[int] = ~[1, 2, 3, 4]; + * assert_eq!(do product |f| { xs.each(f) }, 24); + * ~~~~ + */ +#[cfg(not(stage0))] +#[inline(always)] +pub fn product<T: One + Mul<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T { + fold_ref(One::one::<T>(), iter, |a, x| *a = a.mul(x)) +} + #[cfg(test)] mod tests { use super::*; @@ -254,4 +331,33 @@ mod tests { let xs = ~[8, 2, 3, 1, -5, 9, 11, 15]; assert_eq!(min(|f| xs.each(f)).unwrap(), &-5); } + + #[test] + fn test_fold() { + assert_eq!(fold(0i, |f| int::range(1, 5, f), |a, x| *a += x), 10); + } + + #[test] + fn test_sum() { + let xs: ~[int] = ~[1, 2, 3, 4]; + assert_eq!(do sum |f| { xs.each(f) }, 10); + } + + #[test] + fn test_empty_sum() { + let xs: ~[int] = ~[]; + assert_eq!(do sum |f| { xs.each(f) }, 0); + } + + #[test] + fn test_product() { + let xs: ~[int] = ~[1, 2, 3, 4]; + assert_eq!(do product |f| { xs.each(f) }, 24); + } + + #[test] + fn test_empty_product() { + let xs: ~[int] = ~[]; + assert_eq!(do product |f| { xs.each(f) }, 1); + } } |
