2013-02-26 10:02:53 +01:00
|
|
|
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
2012-12-03 16:48:01 -08:00
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2013-04-24 20:35:49 -04:00
|
|
|
/*! Composable internal iterators
|
2012-09-19 16:52:32 -07:00
|
|
|
|
2013-04-24 20:35:49 -04:00
|
|
|
Internal iterators are functions implementing the protocol used by the `for` loop.
|
2012-09-19 16:52:32 -07:00
|
|
|
|
2013-04-24 20:35:49 -04:00
|
|
|
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:
|
2012-08-27 16:26:35 -07:00
|
|
|
|
2013-05-27 09:49:54 -04:00
|
|
|
~~~ {.rust}
|
2013-05-08 18:49:32 -04:00
|
|
|
println(iter::to_vec(|f| uint::range(0, 20, f)).to_str());
|
2013-05-27 09:49:54 -04:00
|
|
|
~~~
|
2012-01-31 18:52:20 -08:00
|
|
|
|
2013-04-24 20:35:49 -04:00
|
|
|
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:
|
2013-02-07 19:35:18 -05:00
|
|
|
|
2013-05-27 09:49:54 -04:00
|
|
|
~~~ {.rust}
|
2013-04-24 20:35:49 -04:00
|
|
|
use core::iterator::*;
|
2013-03-13 20:55:42 -04:00
|
|
|
|
2013-04-24 20:35:49 -04:00
|
|
|
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());
|
2012-08-27 16:26:35 -07:00
|
|
|
}
|
2013-05-27 09:49:54 -04:00
|
|
|
~~~
|
2012-08-27 16:26:35 -07:00
|
|
|
|
2013-04-24 20:35:49 -04:00
|
|
|
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.
|
2013-04-16 16:11:16 -07:00
|
|
|
|
2013-04-24 20:35:49 -04:00
|
|
|
*/
|
2012-07-11 15:00:40 -07:00
|
|
|
|
2013-05-19 19:46:54 -07:00
|
|
|
use cmp::Ord;
|
|
|
|
use option::{Option, Some, None};
|
|
|
|
use vec::OwnedVector;
|
|
|
|
use num::{One, Zero};
|
|
|
|
use ops::{Add, Mul};
|
2013-04-30 13:01:20 -04:00
|
|
|
|
2013-05-02 18:33:18 -04:00
|
|
|
pub trait Times {
|
|
|
|
fn times(&self, it: &fn() -> bool) -> bool;
|
|
|
|
}
|
2012-10-01 16:36:15 -07:00
|
|
|
|
2012-08-24 14:45:02 -07:00
|
|
|
/**
|
2013-04-24 20:35:49 -04:00
|
|
|
* Transform an internal iterator into an owned vector.
|
2012-08-24 14:45:02 -07:00
|
|
|
*
|
2013-04-24 20:35:49 -04:00
|
|
|
* # Example:
|
2012-08-24 14:45:02 -07:00
|
|
|
*
|
2013-05-27 09:49:54 -04:00
|
|
|
* ~~~ {.rust}
|
2013-04-24 20:35:49 -04:00
|
|
|
* let xs = ~[1, 2, 3];
|
2013-05-08 18:49:32 -04:00
|
|
|
* let ys = do iter::to_vec |f| { xs.each(|x| f(*x)) };
|
2013-04-24 20:35:49 -04:00
|
|
|
* assert_eq!(xs, ys);
|
|
|
|
* ~~~
|
2012-08-24 14:45:02 -07:00
|
|
|
*/
|
|
|
|
#[inline(always)]
|
2013-05-02 18:33:18 -04:00
|
|
|
pub fn to_vec<T>(iter: &fn(f: &fn(T) -> bool) -> bool) -> ~[T] {
|
2013-04-24 20:35:49 -04:00
|
|
|
let mut v = ~[];
|
|
|
|
for iter |x| { v.push(x) }
|
|
|
|
v
|
2012-08-24 14:45:02 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-04-24 20:35:49 -04:00
|
|
|
* Return true if `predicate` is true for any values yielded by an internal iterator.
|
2012-08-24 14:45:02 -07:00
|
|
|
*
|
2013-04-24 20:35:49 -04:00
|
|
|
* Example:
|
2012-08-24 14:45:02 -07:00
|
|
|
*
|
2013-05-27 09:49:54 -04:00
|
|
|
* ~~~ {.rust}
|
2013-04-24 20:35:49 -04:00
|
|
|
* 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)));
|
2013-05-27 09:49:54 -04:00
|
|
|
* ~~~
|
2012-08-24 14:45:02 -07:00
|
|
|
*/
|
|
|
|
#[inline(always)]
|
2013-05-02 18:33:18 -04:00
|
|
|
pub fn any<T>(predicate: &fn(T) -> bool,
|
|
|
|
iter: &fn(f: &fn(T) -> bool) -> bool) -> bool {
|
2013-05-03 16:33:33 -04:00
|
|
|
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:
|
|
|
|
*
|
2013-05-27 09:49:54 -04:00
|
|
|
* ~~~ {.rust}
|
2013-05-03 16:33:33 -04:00
|
|
|
* assert!(all(|&x: &uint| x < 6, |f| uint::range(1, 6, f)));
|
|
|
|
* assert!(!all(|&x: &uint| x < 5, |f| uint::range(1, 6, f)));
|
2013-05-27 09:49:54 -04:00
|
|
|
* ~~~
|
2013-05-03 16:33:33 -04:00
|
|
|
*/
|
|
|
|
#[inline(always)]
|
2013-05-02 18:33:18 -04:00
|
|
|
pub fn all<T>(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))
|
2012-08-24 14:45:02 -07:00
|
|
|
}
|
|
|
|
|
2013-04-30 13:01:20 -04:00
|
|
|
/**
|
2013-04-30 13:28:20 -04:00
|
|
|
* Return the first element where `predicate` returns `true`. Return `None` if no element is found.
|
2013-04-30 13:01:20 -04:00
|
|
|
*
|
|
|
|
* # Example:
|
|
|
|
*
|
2013-05-27 09:49:54 -04:00
|
|
|
* ~~~ {.rust}
|
2013-04-30 13:01:20 -04:00
|
|
|
* let xs = ~[1u, 2, 3, 4, 5, 6];
|
|
|
|
* assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.each(f)).unwrap(), 4);
|
2013-05-27 09:49:54 -04:00
|
|
|
* ~~~
|
2013-04-30 13:01:20 -04:00
|
|
|
*/
|
|
|
|
#[inline(always)]
|
2013-05-02 18:33:18 -04:00
|
|
|
pub fn find<T>(predicate: &fn(&T) -> bool,
|
|
|
|
iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
|
2013-04-30 13:01:20 -04:00
|
|
|
for iter |x| {
|
|
|
|
if predicate(&x) {
|
|
|
|
return Some(x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
2013-04-30 13:28:20 -04:00
|
|
|
/**
|
|
|
|
* Return the largest item yielded by an iterator. Return `None` if the iterator is empty.
|
|
|
|
*
|
|
|
|
* # Example:
|
|
|
|
*
|
2013-05-27 09:49:54 -04:00
|
|
|
* ~~~ {.rust}
|
2013-04-30 13:28:20 -04:00
|
|
|
* let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
|
|
|
|
* assert_eq!(max(|f| xs.each(f)).unwrap(), &15);
|
2013-05-27 09:49:54 -04:00
|
|
|
* ~~~
|
2013-04-30 13:28:20 -04:00
|
|
|
*/
|
|
|
|
#[inline]
|
2013-05-02 18:33:18 -04:00
|
|
|
pub fn max<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
|
2013-04-30 13:28:20 -04:00
|
|
|
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:
|
|
|
|
*
|
2013-05-27 09:49:54 -04:00
|
|
|
* ~~~ {.rust}
|
2013-04-30 13:28:20 -04:00
|
|
|
* let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
|
|
|
|
* assert_eq!(max(|f| xs.each(f)).unwrap(), &-5);
|
2013-05-27 09:49:54 -04:00
|
|
|
* ~~~
|
2013-04-30 13:28:20 -04:00
|
|
|
*/
|
|
|
|
#[inline]
|
2013-05-02 18:33:18 -04:00
|
|
|
pub fn min<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
|
2013-04-30 13:28:20 -04:00
|
|
|
let mut result = None;
|
|
|
|
for iter |x| {
|
|
|
|
match result {
|
|
|
|
Some(ref mut y) => {
|
|
|
|
if x < *y {
|
|
|
|
*y = x;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None => result = Some(x)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
result
|
|
|
|
}
|
|
|
|
|
2013-05-16 19:29:53 -04:00
|
|
|
/**
|
|
|
|
* Reduce an iterator to an accumulated value.
|
|
|
|
*
|
|
|
|
* # Example:
|
|
|
|
*
|
2013-05-27 09:49:54 -04:00
|
|
|
* ~~~ {.rust}
|
2013-05-16 19:29:53 -04:00
|
|
|
* assert_eq!(fold(0i, |f| int::range(1, 5, f), |a, x| *a += x), 10);
|
2013-05-27 09:49:54 -04:00
|
|
|
* ~~~
|
2013-05-16 19:29:53 -04:00
|
|
|
*/
|
|
|
|
#[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:
|
|
|
|
*
|
2013-05-27 09:49:54 -04:00
|
|
|
* ~~~ {.rust}
|
2013-05-16 19:29:53 -04:00
|
|
|
* 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))
|
|
|
|
* }
|
2013-05-27 09:49:54 -04:00
|
|
|
* ~~~
|
2013-05-16 19:29:53 -04:00
|
|
|
*/
|
|
|
|
#[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:
|
|
|
|
*
|
2013-05-27 09:49:54 -04:00
|
|
|
* ~~~ {.rust}
|
2013-05-16 19:29:53 -04:00
|
|
|
* let xs: ~[int] = ~[1, 2, 3, 4];
|
|
|
|
* assert_eq!(do sum |f| { xs.each(f) }, 10);
|
2013-05-27 09:49:54 -04:00
|
|
|
* ~~~
|
2013-05-16 19:29:53 -04:00
|
|
|
*/
|
|
|
|
#[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:
|
|
|
|
*
|
2013-05-27 09:49:54 -04:00
|
|
|
* ~~~ {.rust}
|
2013-05-16 19:29:53 -04:00
|
|
|
* let xs: ~[int] = ~[1, 2, 3, 4];
|
|
|
|
* assert_eq!(do product |f| { xs.each(f) }, 24);
|
2013-05-27 09:49:54 -04:00
|
|
|
* ~~~
|
2013-05-16 19:29:53 -04:00
|
|
|
*/
|
|
|
|
#[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))
|
|
|
|
}
|
|
|
|
|
2013-04-24 20:35:49 -04:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
use prelude::*;
|
2012-08-24 14:45:02 -07:00
|
|
|
|
2013-04-24 20:35:49 -04:00
|
|
|
#[test]
|
2013-05-08 18:49:32 -04:00
|
|
|
fn test_to_vec() {
|
2013-04-24 20:35:49 -04:00
|
|
|
let xs = ~[1, 2, 3];
|
2013-05-08 18:49:32 -04:00
|
|
|
let ys = do to_vec |f| { xs.each(|x| f(*x)) };
|
2013-04-24 20:35:49 -04:00
|
|
|
assert_eq!(xs, ys);
|
2012-08-24 14:45:02 -07:00
|
|
|
}
|
2013-04-10 16:57:52 +02:00
|
|
|
|
2013-04-24 20:35:49 -04:00
|
|
|
#[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)));
|
|
|
|
}
|
2013-04-10 16:57:52 +02:00
|
|
|
|
2013-04-24 20:35:49 -04:00
|
|
|
#[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)));
|
|
|
|
}
|
2013-04-30 13:01:20 -04:00
|
|
|
|
|
|
|
#[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);
|
|
|
|
}
|
2013-04-30 13:28:20 -04:00
|
|
|
|
|
|
|
#[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);
|
|
|
|
}
|
2013-05-16 19:29:53 -04:00
|
|
|
|
|
|
|
#[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);
|
|
|
|
}
|
2013-04-10 16:57:52 +02:00
|
|
|
}
|