auto merge of #8265 : blake2-ppc/rust/std-iter, r=thestinger

Fix #8228 by replacing .iter() and .iter_err() in Result by external iterators.

Implement random access for `iterator::Invert` and `vec::ChunkIter` (and bidirectionality).

Implement Repeat iterator.
This commit is contained in:
bors 2013-08-05 22:38:15 -07:00
commit f8cf234b34
8 changed files with 197 additions and 163 deletions

View File

@ -13,7 +13,7 @@
use std::cmp;
use std::iterator::RandomAccessIterator;
use std::iterator::{Invert, Enumerate};
use std::iterator::{Invert, Enumerate, Repeat, Map, Zip};
use std::num;
use std::ops;
use std::uint;
@ -206,14 +206,13 @@ impl BigBitv {
#[inline]
pub fn equals(&self, b: &BigBitv, nbits: uint) -> bool {
let len = b.storage.len();
do uint::iterate(0, len) |i| {
for i in range(0, len) {
let mask = big_mask(nbits, i);
if mask & self.storage[i] != mask & b.storage[i] {
false
} else {
true
return false;
}
}
true
}
}
@ -864,13 +863,12 @@ impl BitvSet {
/// w1, w2) where the bit location is the number of bits offset so far,
/// and w1/w2 are the words coming from the two vectors self, other.
fn common_iter<'a>(&'a self, other: &'a BitvSet)
-> MapE<(uint,&uint),(uint,uint,uint), &'a ~[uint],Enumerate<vec::VecIterator<'a,uint>>> {
let min = num::min(self.bitv.storage.len(),
other.bitv.storage.len());
MapE{iter: self.bitv.storage.slice(0, min).iter().enumerate(),
env: &other.bitv.storage,
f: |(i, &w): (uint, &uint), o_store| (i * uint::bits, w, o_store[i])
}
-> Map<'static, ((uint, &'a uint), &'a ~[uint]), (uint, uint, uint),
Zip<Enumerate<vec::VecIterator<'a, uint>>, Repeat<&'a ~[uint]>>> {
let min = num::min(self.bitv.storage.len(), other.bitv.storage.len());
self.bitv.storage.slice(0, min).iter().enumerate()
.zip(Repeat::new(&other.bitv.storage))
.transform(|((i, &w), o_store)| (i * uint::bits, w, o_store[i]))
}
/// Visits each word in self or other that extends beyond the other. This
@ -881,47 +879,23 @@ impl BitvSet {
/// is true if the word comes from 'self', and false if it comes from
/// 'other'.
fn outlier_iter<'a>(&'a self, other: &'a BitvSet)
-> MapE<(uint, &uint),(bool, uint, uint), uint, Enumerate<vec::VecIterator<'a, uint>>> {
let len1 = self.bitv.storage.len();
let len2 = other.bitv.storage.len();
let min = num::min(len1, len2);
-> Map<'static, ((uint, &'a uint), uint), (bool, uint, uint),
Zip<Enumerate<vec::VecIterator<'a, uint>>, Repeat<uint>>> {
let slen = self.bitv.storage.len();
let olen = other.bitv.storage.len();
if min < len1 {
MapE{iter: self.bitv.storage.slice(min, len1).iter().enumerate(),
env: min,
f: |(i, &w): (uint, &uint), min| (true, (i + min) * uint::bits, w)
}
if olen < slen {
self.bitv.storage.slice_from(olen).iter().enumerate()
.zip(Repeat::new(olen))
.transform(|((i, &w), min)| (true, (i + min) * uint::bits, w))
} else {
MapE{iter: other.bitv.storage.slice(min, len2).iter().enumerate(),
env: min,
f: |(i, &w): (uint, &uint), min| (false, (i + min) * uint::bits, w)
}
other.bitv.storage.slice_from(slen).iter().enumerate()
.zip(Repeat::new(slen))
.transform(|((i, &w), min)| (false, (i + min) * uint::bits, w))
}
}
}
/// Like iterator::Map with explicit env capture
struct MapE<A, B, Env, I> {
priv env: Env,
priv f: &'static fn(A, Env) -> B,
priv iter: I,
}
impl<'self, A, B, Env: Clone, I: Iterator<A>> Iterator<B> for MapE<A, B, Env, I> {
#[inline]
fn next(&mut self) -> Option<B> {
match self.iter.next() {
Some(elt) => Some((self.f)(elt, self.env.clone())),
None => None
}
}
#[inline]
fn size_hint(&self) -> (uint, Option<uint>) {
self.iter.size_hint()
}
}
pub struct BitvSetIterator<'self> {
priv set: &'self BitvSet,
priv next_idx: uint

View File

@ -19,7 +19,8 @@ use container::{Container, Mutable, Map, MutableMap, Set, MutableSet};
use clone::Clone;
use cmp::{Eq, Equiv};
use hash::Hash;
use iterator::{Iterator, IteratorUtil, FromIterator, Extendable, Chain, range};
use iterator::{Iterator, IteratorUtil, FromIterator, Extendable, range};
use iterator::{FilterMap, Chain, Repeat, Zip};
use num;
use option::{None, Option, Some};
use rand::RngUtil;
@ -712,10 +713,12 @@ impl<T:Hash + Eq> HashSet<T> {
}
/// Visit the values representing the difference
pub fn difference_iter<'a>(&'a self, other: &'a HashSet<T>)
-> SetAlgebraIter<'a, T> {
EnvFilterIterator{iter: self.iter(), env: other,
filter: |elt, other| !other.contains(elt) }
pub fn difference_iter<'a>(&'a self, other: &'a HashSet<T>) -> SetAlgebraIter<'a, T> {
Repeat::new(other)
.zip(self.iter())
.filter_map(|(other, elt)| {
if !other.contains(elt) { Some(elt) } else { None }
})
}
/// Visit the values representing the symmetric difference
@ -727,8 +730,11 @@ impl<T:Hash + Eq> HashSet<T> {
/// Visit the values representing the intersection
pub fn intersection_iter<'a>(&'a self, other: &'a HashSet<T>)
-> SetAlgebraIter<'a, T> {
EnvFilterIterator{iter: self.iter(), env: other,
filter: |elt, other| other.contains(elt) }
Repeat::new(other)
.zip(self.iter())
.filter_map(|(other, elt)| {
if other.contains(elt) { Some(elt) } else { None }
})
}
/// Visit the values representing the union
@ -756,38 +762,12 @@ impl<K: Eq + Hash, T: Iterator<K>> Extendable<K, T> for HashSet<K> {
}
}
// FIXME #7814: use std::iterator::FilterIterator
/// Building block for Set operation iterators
pub struct EnvFilterIterator<A, Env, I> {
priv env: Env,
priv filter: &'static fn(&A, Env) -> bool,
priv iter: I,
}
impl<'self, A, Env: Clone, I: Iterator<&'self A>> Iterator<&'self A>
for EnvFilterIterator<A, Env, I> {
#[inline]
fn next(&mut self) -> Option<&'self A> {
loop {
match self.iter.next() {
Some(elt) => if (self.filter)(elt, self.env.clone()) {
return Some(elt)
},
None => return None,
}
}
}
#[inline]
fn size_hint(&self) -> (uint, Option<uint>) {
let (_, upper) = self.iter.size_hint();
(0, upper)
}
}
// `Repeat` is used to feed the filter closure an explicit capture
// of a reference to the other set
/// Set operations iterator
pub type SetAlgebraIter<'self, T> =
EnvFilterIterator<T, &'self HashSet<T>, HashSetIterator<'self, T>>;
FilterMap<'static,(&'self HashSet<T>, &'self T), &'self T,
Zip<Repeat<&'self HashSet<T>>,HashSetIterator<'self,T>>>;
#[cfg(test)]

View File

@ -82,6 +82,17 @@ pub trait DoubleEndedIteratorUtil {
/// In the future these will be default methods instead of a utility trait.
impl<A, T: DoubleEndedIterator<A>> DoubleEndedIteratorUtil for T {
/// Flip the direction of the iterator
///
/// The inverted iterator flips the ends on an iterator that can already
/// be iterated from the front and from the back.
///
///
/// If the iterator also implements RandomAccessIterator, the inverted
/// iterator is also random access, with the indices starting at the back
/// of the original iterator.
///
/// Note: Random access with inverted indices still only applies to the first
/// `uint::max_value` elements of the original iterator.
#[inline]
fn invert(self) -> Invert<T> {
Invert{iter: self}
@ -106,6 +117,16 @@ impl<A, T: DoubleEndedIterator<A>> DoubleEndedIterator<A> for Invert<T> {
fn next_back(&mut self) -> Option<A> { self.iter.next() }
}
impl<A, T: DoubleEndedIterator<A> + RandomAccessIterator<A>> RandomAccessIterator<A>
for Invert<T> {
#[inline]
fn indexable(&self) -> uint { self.iter.indexable() }
#[inline]
fn idx(&self, index: uint) -> Option<A> {
self.iter.idx(self.indexable() - index - 1)
}
}
/// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also
/// implementations of the `Iterator` trait.
///
@ -1555,6 +1576,39 @@ impl<A: Add<A, A> + Clone> Iterator<A> for Counter<A> {
}
}
/// An iterator that repeats an element endlessly
#[deriving(Clone, DeepClone)]
pub struct Repeat<A> {
priv element: A
}
impl<A: Clone> Repeat<A> {
/// Create a new `Repeat` that enlessly repeats the element `elt`.
#[inline]
pub fn new(elt: A) -> Repeat<A> {
Repeat{element: elt}
}
}
impl<A: Clone> Iterator<A> for Repeat<A> {
#[inline]
fn next(&mut self) -> Option<A> { self.idx(0) }
#[inline]
fn size_hint(&self) -> (uint, Option<uint>) { (uint::max_value, None) }
}
impl<A: Clone> DoubleEndedIterator<A> for Repeat<A> {
#[inline]
fn next_back(&mut self) -> Option<A> { self.idx(0) }
}
impl<A: Clone> RandomAccessIterator<A> for Repeat<A> {
#[inline]
fn indexable(&self) -> uint { uint::max_value }
#[inline]
fn idx(&self, _: uint) -> Option<A> { Some(self.element.clone()) }
}
#[cfg(test)]
mod tests {
use super::*;
@ -2017,6 +2071,17 @@ mod tests {
check_randacc_iter(xs.iter().enumerate(), xs.len());
}
#[test]
fn test_random_access_invert() {
let xs = [1, 2, 3, 4, 5];
check_randacc_iter(xs.iter().invert(), xs.len());
let mut it = xs.iter().invert();
it.next();
it.next_back();
it.next();
check_randacc_iter(it, xs.len() - 3);
}
#[test]
fn test_random_access_zip() {
let xs = [1, 2, 3, 4, 5];

View File

@ -70,30 +70,6 @@ pub fn div_round(x: uint, y: uint) -> uint {
///
pub fn div_floor(x: uint, y: uint) -> uint { return x / y; }
///
/// Iterate over the range [`lo`..`hi`), or stop when requested
///
/// # Arguments
///
/// * lo - The integer at which to start the loop (included)
/// * hi - The integer at which to stop the loop (excluded)
/// * it - A block to execute with each consecutive integer of the range.
/// Return `true` to continue, `false` to stop.
///
/// # Return value
///
/// `true` If execution proceeded correctly, `false` if it was interrupted,
/// that is if `it` returned `false` at any point.
///
pub fn iterate(lo: uint, hi: uint, it: &fn(uint) -> bool) -> bool {
let mut i = lo;
while i < hi {
if (!it(i)) { return false; }
i += 1u;
}
return true;
}
impl iter::Times for uint {
#[inline]
///

View File

@ -116,7 +116,7 @@ impl<T: ToStr> ToStr for Option<T> {
impl<T> Option<T> {
/// Return an iterator over the possibly contained value
#[inline]
pub fn iter<'r>(&'r self) -> OptionIterator<'r, T> {
pub fn iter<'r>(&'r self) -> OptionIterator<&'r T> {
match *self {
Some(ref x) => OptionIterator{opt: Some(x)},
None => OptionIterator{opt: None}
@ -125,13 +125,19 @@ impl<T> Option<T> {
/// Return a mutable iterator over the possibly contained value
#[inline]
pub fn mut_iter<'r>(&'r mut self) -> OptionMutIterator<'r, T> {
pub fn mut_iter<'r>(&'r mut self) -> OptionIterator<&'r mut T> {
match *self {
Some(ref mut x) => OptionMutIterator{opt: Some(x)},
None => OptionMutIterator{opt: None}
Some(ref mut x) => OptionIterator{opt: Some(x)},
None => OptionIterator{opt: None}
}
}
/// Return a consuming iterator over the possibly contained value
#[inline]
pub fn consume(self) -> OptionIterator<T> {
OptionIterator{opt: self}
}
/// Returns true if the option equals `None`
#[inline]
pub fn is_none(&self) -> bool {
@ -404,34 +410,18 @@ impl<T> Zero for Option<T> {
fn is_zero(&self) -> bool { self.is_none() }
}
/// Immutable iterator over an `Option<A>`
pub struct OptionIterator<'self, A> {
priv opt: Option<&'self A>
/// An iterator that yields either one or zero elements
pub struct OptionIterator<A> {
priv opt: Option<A>
}
impl<'self, A> Iterator<&'self A> for OptionIterator<'self, A> {
fn next(&mut self) -> Option<&'self A> {
util::replace(&mut self.opt, None)
}
fn size_hint(&self) -> (uint, Option<uint>) {
match self.opt {
Some(_) => (1, Some(1)),
None => (0, Some(0)),
}
}
}
/// Mutable iterator over an `Option<A>`
pub struct OptionMutIterator<'self, A> {
priv opt: Option<&'self mut A>
}
impl<'self, A> Iterator<&'self mut A> for OptionMutIterator<'self, A> {
fn next(&mut self) -> Option<&'self mut A> {
util::replace(&mut self.opt, None)
impl<A> Iterator<A> for OptionIterator<A> {
#[inline]
fn next(&mut self) -> Option<A> {
self.opt.take()
}
#[inline]
fn size_hint(&self) -> (uint, Option<uint>) {
match self.opt {
Some(_) => (1, Some(1)),

View File

@ -12,6 +12,7 @@
use cast;
use clone::Clone;
use iterator::{range, Iterator};
use option::{Option, Some, None};
use unstable::intrinsics;
use util::swap;
@ -20,7 +21,6 @@ use util::swap;
#[cfg(not(test))] use num::Int;
#[cfg(not(test))] use cmp::{Eq, Ord};
use uint;
/// Calculate the offset from a pointer
#[inline]
@ -240,11 +240,10 @@ pub unsafe fn array_each_with_len<T>(arr: **T, len: uint, cb: &fn(*T)) {
fail!("ptr::array_each_with_len failure: arr input is null pointer");
}
//let start_ptr = *arr;
uint::iterate(0, len, |e| {
for e in range(0, len) {
let n = offset(arr, e as int);
cb(*n);
true
});
}
debug!("array_each_with_len: after iterate");
}

View File

@ -16,7 +16,7 @@ use clone::Clone;
use cmp::Eq;
use either;
use iterator::Iterator;
use option::{None, Option, Some};
use option::{None, Option, Some, OptionIterator};
use vec;
use vec::{OwnedVector, ImmutableVector};
use container::Container;
@ -86,15 +86,15 @@ impl<T, E: ToStr> Result<T, E> {
///
/// Example:
///
/// do read_file(file).iter |buf| {
/// for buf in read_file(file) {
/// print_buf(buf)
/// }
#[inline]
pub fn iter(&self, f: &fn(&T)) {
pub fn iter<'r>(&'r self) -> OptionIterator<&'r T> {
match *self {
Ok(ref t) => f(t),
Err(_) => (),
}
Ok(ref t) => Some(t),
Err(*) => None,
}.consume()
}
/// Call a method based on a previous result
@ -104,11 +104,11 @@ impl<T, E: ToStr> Result<T, E> {
/// immediately returned. This function can be used to pass through a
/// successful result while handling an error.
#[inline]
pub fn iter_err(&self, f: &fn(&E)) {
pub fn iter_err<'r>(&'r self) -> OptionIterator<&'r E> {
match *self {
Ok(_) => (),
Err(ref e) => f(e),
}
Ok(*) => None,
Err(ref t) => Some(t),
}.consume()
}
/// Unwraps a result, yielding the content of an `Ok`.
@ -214,7 +214,7 @@ impl<T, E: Clone + ToStr> Result<T, E> {
/// parse_bytes(buf)
/// };
#[inline]
pub fn map<U: Clone>(&self, op: &fn(&T) -> U) -> Result<U,E> {
pub fn map<U>(&self, op: &fn(&T) -> U) -> Result<U,E> {
match *self {
Ok(ref t) => Ok(op(t)),
Err(ref e) => Err(e.clone())
@ -335,21 +335,25 @@ mod tests {
#[test]
pub fn test_impl_iter() {
let mut valid = false;
Ok::<~str, ~str>(~"a").iter(|_x| valid = true);
let okval = Ok::<~str, ~str>(~"a");
do okval.iter().next().map |_| { valid = true; };
assert!(valid);
Err::<~str, ~str>(~"b").iter(|_x| valid = false);
let errval = Err::<~str, ~str>(~"b");
do errval.iter().next().map |_| { valid = false; };
assert!(valid);
}
#[test]
pub fn test_impl_iter_err() {
let mut valid = true;
Ok::<~str, ~str>(~"a").iter_err(|_x| valid = false);
let okval = Ok::<~str, ~str>(~"a");
do okval.iter_err().next().map |_| { valid = false };
assert!(valid);
valid = false;
Err::<~str, ~str>(~"b").iter_err(|_x| valid = true);
let errval = Err::<~str, ~str>(~"b");
do errval.iter_err().next().map |_| { valid = true };
assert!(valid);
}

View File

@ -479,6 +479,7 @@ pub fn each_permutation<T:Clone>(values: &[T], fun: &fn(perm : &[T]) -> bool) ->
/// An iterator over the (overlapping) slices of length `size` within
/// a vector.
#[deriving(Clone)]
pub struct WindowIter<'self, T> {
priv v: &'self [T],
priv size: uint
@ -498,6 +499,10 @@ impl<'self, T> Iterator<&'self [T]> for WindowIter<'self, T> {
/// An iterator over a vector in (non-overlapping) chunks (`size`
/// elements at a time).
///
/// When the vector len is not evenly divided by the chunk size,
/// the last slice of the iteration will be the remainer.
#[deriving(Clone)]
pub struct ChunkIter<'self, T> {
priv v: &'self [T],
priv size: uint
@ -505,16 +510,49 @@ pub struct ChunkIter<'self, T> {
impl<'self, T> Iterator<&'self [T]> for ChunkIter<'self, T> {
fn next(&mut self) -> Option<&'self [T]> {
if self.size == 0 {
if self.v.len() == 0 {
None
} else if self.size >= self.v.len() {
// finished
self.size = 0;
Some(self.v)
} else {
let ret = Some(self.v.slice(0, self.size));
self.v = self.v.slice(self.size, self.v.len());
ret
let chunksz = cmp::min(self.v.len(), self.size);
let (fst, snd) = (self.v.slice_to(chunksz),
self.v.slice_from(chunksz));
self.v = snd;
Some(fst)
}
}
}
impl<'self, T> DoubleEndedIterator<&'self [T]> for ChunkIter<'self, T> {
fn next_back(&mut self) -> Option<&'self [T]> {
if self.v.len() == 0 {
None
} else {
let remainder = self.v.len() % self.size;
let chunksz = if remainder != 0 { remainder } else { self.size };
let (fst, snd) = (self.v.slice_to(self.v.len() - chunksz),
self.v.slice_from(self.v.len() - chunksz));
self.v = fst;
Some(snd)
}
}
}
impl<'self, T> RandomAccessIterator<&'self [T]> for ChunkIter<'self, T> {
#[inline]
fn indexable(&self) -> uint {
self.v.len()/self.size + if self.v.len() % self.size != 0 { 1 } else { 0 }
}
#[inline]
fn idx(&self, index: uint) -> Option<&'self [T]> {
if index < self.indexable() {
let lo = index * self.size;
let mut hi = lo + self.size;
if hi < lo || hi > self.v.len() { hi = self.v.len(); }
Some(self.v.slice(lo, hi))
} else {
None
}
}
}
@ -3378,6 +3416,14 @@ mod tests {
assert_eq!(v.chunk_iter(2).collect::<~[&[int]]>(), ~[&[1i,2], &[3,4], &[5]]);
assert_eq!(v.chunk_iter(3).collect::<~[&[int]]>(), ~[&[1i,2,3], &[4,5]]);
assert_eq!(v.chunk_iter(6).collect::<~[&[int]]>(), ~[&[1i,2,3,4,5]]);
assert_eq!(v.chunk_iter(2).invert().collect::<~[&[int]]>(), ~[&[5i], &[3,4], &[1,2]]);
let it = v.chunk_iter(2);
assert_eq!(it.indexable(), 3);
assert_eq!(it.idx(0).unwrap(), &[1,2]);
assert_eq!(it.idx(1).unwrap(), &[3,4]);
assert_eq!(it.idx(2).unwrap(), &[5]);
assert_eq!(it.idx(3), None);
}
#[test]