rust/src/libcore/iter.rs

232 lines
5.7 KiB
Rust
Raw Normal View History

// 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 <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 19:35:49 -05:00
/*! Composable internal iterators
2013-04-24 19:35:49 -05:00
Internal iterators are functions implementing the protocol used by the `for` loop.
2013-04-24 19:35:49 -05: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 18:26:35 -05:00
2013-04-24 19:35:49 -05:00
~~~~
println(iter::to_vec(|f| uint::range(0, 20, f)).to_str());
2013-04-24 19:35:49 -05:00
~~~~
2013-04-24 19:35:49 -05: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 18:35:18 -06:00
2013-04-24 19:35:49 -05:00
~~~~
use core::iterator::*;
2013-03-13 19:55:42 -05:00
2013-04-24 19:35:49 -05: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 18:26:35 -05:00
}
2013-04-24 19:35:49 -05:00
~~~~
2012-08-27 18:26:35 -05:00
2013-04-24 19:35:49 -05: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-24 19:35:49 -05:00
*/
2013-05-02 17:33:18 -05:00
#[cfg(not(stage0))] use cmp::Ord;
#[cfg(not(stage0))] use option::{Option, Some, None};
2013-04-30 12:01:20 -05:00
2013-05-02 17:33:18 -05:00
#[cfg(stage0)]
pub trait Times {
fn times(&self, it: &fn() -> bool);
}
2013-05-02 17:33:18 -05:00
#[cfg(not(stage0))]
pub trait Times {
fn times(&self, it: &fn() -> bool) -> bool;
}
/**
2013-04-24 19:35:49 -05:00
* Transform an internal iterator into an owned vector.
*
2013-04-24 19:35:49 -05:00
* # Example:
*
2013-04-24 19:35:49 -05:00
* ~~~
* let xs = ~[1, 2, 3];
* let ys = do iter::to_vec |f| { xs.each(|x| f(*x)) };
2013-04-24 19:35:49 -05:00
* assert_eq!(xs, ys);
* ~~~
*/
#[inline(always)]
2013-05-02 17:33:18 -05:00
#[cfg(not(stage0))]
pub fn to_vec<T>(iter: &fn(f: &fn(T) -> bool) -> bool) -> ~[T] {
2013-04-24 19:35:49 -05:00
let mut v = ~[];
for iter |x| { v.push(x) }
v
}
/**
2013-04-24 19:35:49 -05:00
* Return true if `predicate` is true for any values yielded by an internal iterator.
*
2013-04-24 19:35:49 -05:00
* Example:
*
2013-04-24 19:35:49 -05: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)));
* ~~~~
*/
#[inline(always)]
2013-05-02 17:33:18 -05:00
#[cfg(not(stage0))]
pub fn any<T>(predicate: &fn(T) -> bool,
iter: &fn(f: &fn(T) -> bool) -> bool) -> bool {
// If the predicate returns true, we break. If we ever broke, then we found
// something
!iter(|x| !predicate(x))
}
/**
2013-04-24 19:35:49 -05:00
* Return true if `predicate` is true for all values yielded by an internal iterator.
*
2013-04-24 19:35:49 -05:00
* # Example:
*
2013-04-24 19:35:49 -05: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)));
* ~~~~
*/
#[inline(always)]
2013-05-02 17:33:18 -05:00
#[cfg(not(stage0))]
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))
}
2013-04-30 12:01:20 -05:00
/**
2013-04-30 12:28:20 -05:00
* Return the first element where `predicate` returns `true`. Return `None` if no element is found.
2013-04-30 12:01:20 -05:00
*
* # Example:
*
* ~~~~
* let xs = ~[1u, 2, 3, 4, 5, 6];
* assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.each(f)).unwrap(), 4);
* ~~~~
*/
#[inline(always)]
2013-05-02 17:33:18 -05:00
#[cfg(not(stage0))]
pub fn find<T>(predicate: &fn(&T) -> bool,
iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
2013-04-30 12:01:20 -05:00
for iter |x| {
if predicate(&x) {
return Some(x);
}
}
None
}
2013-04-30 12:28:20 -05:00
/**
* 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]
2013-05-02 17:33:18 -05:00
#[cfg(not(stage0))]
pub fn max<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
2013-04-30 12:28:20 -05: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:
*
* ~~~~
* let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
* assert_eq!(max(|f| xs.each(f)).unwrap(), &-5);
* ~~~~
*/
#[inline]
2013-05-02 17:33:18 -05:00
#[cfg(not(stage0))]
pub fn min<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
2013-04-30 12:28:20 -05: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-04-24 19:35:49 -05:00
#[cfg(test)]
mod tests {
use super::*;
use prelude::*;
2013-04-24 19:35:49 -05:00
#[test]
fn test_to_vec() {
2013-04-24 19:35:49 -05:00
let xs = ~[1, 2, 3];
let ys = do to_vec |f| { xs.each(|x| f(*x)) };
2013-04-24 19:35:49 -05:00
assert_eq!(xs, ys);
}
2013-04-10 09:57:52 -05:00
2013-04-24 19:35:49 -05: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 09:57:52 -05:00
2013-04-24 19:35:49 -05: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 12:01:20 -05: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 12:28:20 -05: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-04-10 09:57:52 -05:00
}