// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. /*! Composable internal iterators Internal iterators are functions implementing the protocol used by the `for` loop. An internal iterator takes `fn(...) -> bool` as a parameter, with returning `false` used to signal breaking out of iteration. The adaptors in the module work with any such iterator, not just ones tied to specific traits. For example: ~~~~ println(iter::to_vec(|f| uint::range(0, 20, f)).to_str()); ~~~~ An external iterator object implementing the interface in the `iterator` module can be used as an internal iterator by calling the `advance` method. For example: ~~~~ use core::iterator::*; let xs = [0u, 1, 2, 3, 4, 5]; let ys = [30, 40, 50, 60]; let mut it = xs.iter().chain(ys.iter()); for it.advance |&x: &uint| { println(x.to_str()); } ~~~~ Internal iterators provide a subset of the functionality of an external iterator. It's not possible to interleave them to implement algorithms like `zip`, `union` and `merge`. However, they're often 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 { fn times(&self, it: &fn() -> bool); } #[cfg(not(stage0))] pub trait Times { fn times(&self, it: &fn() -> bool) -> bool; } /** * Transform an internal iterator into an owned vector. * * # Example: * * ~~~ * let xs = ~[1, 2, 3]; * let ys = do iter::to_vec |f| { xs.each(|x| f(*x)) }; * assert_eq!(xs, ys); * ~~~ */ #[inline(always)] #[cfg(not(stage0))] pub fn to_vec(iter: &fn(f: &fn(T) -> bool) -> bool) -> ~[T] { let mut v = ~[]; for iter |x| { v.push(x) } v } /** * Return true if `predicate` is true for any values yielded by an internal iterator. * * Example: * * ~~~~ * let xs = ~[1u, 2, 3, 4, 5]; * assert!(any(|&x: &uint| x > 2, |f| xs.each(f))); * assert!(!any(|&x: &uint| x > 5, |f| xs.each(f))); * ~~~~ */ #[inline(always)] #[cfg(not(stage0))] pub fn any(predicate: &fn(T) -> bool, iter: &fn(f: &fn(T) -> bool) -> bool) -> bool { for iter |x| { if predicate(x) { return true; } } return false; } /** * Return true if `predicate` is true for all values yielded by an internal iterator. * * # Example: * * ~~~~ * assert!(all(|&x: &uint| x < 6, |f| uint::range(1, 6, f))); * assert!(!all(|&x: &uint| x < 5, |f| uint::range(1, 6, f))); * ~~~~ */ #[inline(always)] #[cfg(stage0)] pub fn all(predicate: &fn(T) -> bool, iter: &fn(f: &fn(T) -> bool)) -> bool { for iter |x| { if !predicate(x) { return false; } } return true; } /** * Return true if `predicate` is true for all values yielded by an internal iterator. * * # Example: * * ~~~~ * assert!(all(|&x: &uint| x < 6, |f| uint::range(1, 6, f))); * assert!(!all(|&x: &uint| x < 5, |f| uint::range(1, 6, f))); * ~~~~ */ #[inline(always)] #[cfg(not(stage0))] pub fn all(predicate: &fn(T) -> bool, iter: &fn(f: &fn(T) -> bool) -> bool) -> bool { // If we ever break, iter will return false, so this will only return true // if predicate returns true for everything. iter(|x| predicate(x)) } /** * Return the first element where `predicate` returns `true`. Return `None` if no element is found. * * # Example: * * ~~~~ * let xs = ~[1u, 2, 3, 4, 5, 6]; * assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.each(f)).unwrap(), 4); * ~~~~ */ #[inline(always)] #[cfg(not(stage0))] pub fn find(predicate: &fn(&T) -> bool, iter: &fn(f: &fn(T) -> bool) -> bool) -> Option { for iter |x| { if predicate(&x) { return Some(x); } } None } /** * Return the largest item yielded by an iterator. Return `None` if the iterator is empty. * * # Example: * * ~~~~ * let xs = ~[8, 2, 3, 1, -5, 9, 11, 15]; * assert_eq!(max(|f| xs.each(f)).unwrap(), &15); * ~~~~ */ #[inline] #[cfg(not(stage0))] pub fn max(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option { let mut result = None; for iter |x| { match result { Some(ref mut y) => { if x > *y { *y = x; } } None => result = Some(x) } } result } /** * Return the smallest item yielded by an iterator. Return `None` if the iterator is empty. * * # Example: * * ~~~~ * let xs = ~[8, 2, 3, 1, -5, 9, 11, 15]; * assert_eq!(max(|f| xs.each(f)).unwrap(), &-5); * ~~~~ */ #[inline] #[cfg(not(stage0))] pub fn min(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option { let mut result = None; for iter |x| { match result { Some(ref mut y) => { if x < *y { *y = x; } } None => result = Some(x) } } 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(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>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T { * fold_ref(One::one::(), iter, |a, x| *a = a.mul(x)) * } * ~~~~ */ #[cfg(not(stage0))] #[inline] pub fn fold_ref(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>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T { fold_ref(Zero::zero::(), 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>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T { fold_ref(One::one::(), iter, |a, x| *a = a.mul(x)) } #[cfg(test)] mod tests { use super::*; use prelude::*; #[test] fn test_to_vec() { let xs = ~[1, 2, 3]; let ys = do to_vec |f| { xs.each(|x| f(*x)) }; assert_eq!(xs, ys); } #[test] fn test_any() { let xs = ~[1u, 2, 3, 4, 5]; assert!(any(|&x: &uint| x > 2, |f| xs.each(f))); assert!(!any(|&x: &uint| x > 5, |f| xs.each(f))); } #[test] fn test_all() { assert!(all(|x: uint| x < 6, |f| uint::range(1, 6, f))); assert!(!all(|x: uint| x < 5, |f| uint::range(1, 6, f))); } #[test] fn test_find() { let xs = ~[1u, 2, 3, 4, 5, 6]; assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.each(f)).unwrap(), 4); } #[test] fn test_max() { let xs = ~[8, 2, 3, 1, -5, 9, 11, 15]; assert_eq!(max(|f| xs.each(f)).unwrap(), &15); } #[test] fn test_min() { 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); } }