auto merge of #7570 : kballard/rust/iterator-size-hint, r=thestinger
Change the signature of Iterator.size_hint() to always have a lower bound. Implement .size_hint() on all remaining iterators (if it differs from the default).
This commit is contained in:
commit
a9f178c148
@ -186,6 +186,9 @@ pub struct PriorityQueueIterator <'self, T> {
|
||||
impl<'self, T> Iterator<&'self T> for PriorityQueueIterator<'self, T> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<(&'self T)> { self.iter.next() }
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -198,14 +198,15 @@ impl<K: TotalOrd, V> TreeMap<K, V> {
|
||||
/// Get a lazy iterator over the key-value pairs in the map.
|
||||
/// Requires that it be frozen (immutable).
|
||||
pub fn iter<'a>(&'a self) -> TreeMapIterator<'a, K, V> {
|
||||
TreeMapIterator{stack: ~[], node: &self.root}
|
||||
TreeMapIterator{stack: ~[], node: &self.root, remaining: self.length}
|
||||
}
|
||||
}
|
||||
|
||||
/// Lazy forward iterator over a map
|
||||
pub struct TreeMapIterator<'self, K, V> {
|
||||
priv stack: ~[&'self ~TreeNode<K, V>],
|
||||
priv node: &'self Option<~TreeNode<K, V>>
|
||||
priv node: &'self Option<~TreeNode<K, V>>,
|
||||
priv remaining: uint
|
||||
}
|
||||
|
||||
impl<'self, K, V> Iterator<(&'self K, &'self V)> for TreeMapIterator<'self, K, V> {
|
||||
@ -222,12 +223,18 @@ impl<'self, K, V> Iterator<(&'self K, &'self V)> for TreeMapIterator<'self, K, V
|
||||
None => {
|
||||
let res = self.stack.pop();
|
||||
self.node = &res.right;
|
||||
self.remaining -= 1;
|
||||
return Some((&res.key, &res.value));
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
(self.remaining, Some(self.remaining))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'self, T> Iterator<&'self T> for TreeSetIterator<'self, T> {
|
||||
|
@ -125,9 +125,9 @@ impl<E:CLike> Iterator<E> for EnumSetIterator<E> {
|
||||
Some(elem)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (Option<uint>, Option<uint>) {
|
||||
let exact = Some(self.bits.population_count());
|
||||
(exact, exact)
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
let exact = self.bits.population_count();
|
||||
(exact, Some(exact))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@ use option::{Option, Some, None};
|
||||
use ops::{Add, Mul};
|
||||
use cmp::Ord;
|
||||
use clone::Clone;
|
||||
use uint;
|
||||
|
||||
/// Conversion from an `Iterator`
|
||||
pub trait FromIterator<A, T: Iterator<A>> {
|
||||
@ -43,7 +44,7 @@ pub trait Iterator<A> {
|
||||
/// Return a lower bound and upper bound on the remaining length of the iterator.
|
||||
///
|
||||
/// The common use case for the estimate is pre-allocating space to store the results.
|
||||
fn size_hint(&self) -> (Option<uint>, Option<uint>) { (None, None) }
|
||||
fn size_hint(&self) -> (uint, Option<uint>) { (0, None) }
|
||||
}
|
||||
|
||||
/// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also
|
||||
@ -684,18 +685,18 @@ impl<A, T: Iterator<A>, U: Iterator<A>> Iterator<A> for ChainIterator<A, T, U> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (Option<uint>, Option<uint>) {
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
let (a_lower, a_upper) = self.a.size_hint();
|
||||
let (b_lower, b_upper) = self.b.size_hint();
|
||||
|
||||
let lower = match (a_lower, b_lower) {
|
||||
(Some(x), Some(y)) => Some(x + y),
|
||||
(Some(x), None) => Some(x),
|
||||
(None, Some(y)) => Some(y),
|
||||
(None, None) => None
|
||||
let lower = if uint::max_value - a_lower < b_lower {
|
||||
uint::max_value
|
||||
} else {
|
||||
a_lower + b_lower
|
||||
};
|
||||
|
||||
let upper = match (a_upper, b_upper) {
|
||||
(Some(x), Some(y)) if uint::max_value - x < y => Some(uint::max_value),
|
||||
(Some(x), Some(y)) => Some(x + y),
|
||||
_ => None
|
||||
};
|
||||
@ -719,6 +720,23 @@ impl<A, B, T: Iterator<A>, U: Iterator<B>> Iterator<(A, B)> for ZipIterator<A, T
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
let (a_lower, a_upper) = self.a.size_hint();
|
||||
let (b_lower, b_upper) = self.b.size_hint();
|
||||
|
||||
let lower = cmp::min(a_lower, b_lower);
|
||||
|
||||
let upper = match (a_upper, b_upper) {
|
||||
(Some(x), Some(y)) => Some(cmp::min(x,y)),
|
||||
(Some(x), None) => Some(x),
|
||||
(None, Some(y)) => Some(y),
|
||||
(None, None) => None
|
||||
};
|
||||
|
||||
(lower, upper)
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator which maps the values of `iter` with `f`
|
||||
@ -737,7 +755,7 @@ impl<'self, A, B, T: Iterator<A>> Iterator<B> for MapIterator<'self, A, B, T> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (Option<uint>, Option<uint>) {
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
@ -762,9 +780,9 @@ impl<'self, A, T: Iterator<A>> Iterator<A> for FilterIterator<'self, A, T> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (Option<uint>, Option<uint>) {
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
let (_, upper) = self.iter.size_hint();
|
||||
(None, upper) // can't know a lower bound, due to the predicate
|
||||
(0, upper) // can't know a lower bound, due to the predicate
|
||||
}
|
||||
}
|
||||
|
||||
@ -787,9 +805,9 @@ impl<'self, A, B, T: Iterator<A>> Iterator<B> for FilterMapIterator<'self, A, B,
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (Option<uint>, Option<uint>) {
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
let (_, upper) = self.iter.size_hint();
|
||||
(None, upper) // can't know a lower bound, due to the predicate
|
||||
(0, upper) // can't know a lower bound, due to the predicate
|
||||
}
|
||||
}
|
||||
|
||||
@ -812,6 +830,11 @@ impl<A, T: Iterator<A>> Iterator<(uint, A)> for EnumerateIterator<A, T> {
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator which rejects elements while `predicate` is true
|
||||
@ -844,6 +867,12 @@ impl<'self, A, T: Iterator<A>> Iterator<A> for SkipWhileIterator<'self, A, T> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
let (_, upper) = self.iter.size_hint();
|
||||
(0, upper) // can't know a lower bound, due to the predicate
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator which only accepts elements while `predicate` is true
|
||||
@ -872,6 +901,12 @@ impl<'self, A, T: Iterator<A>> Iterator<A> for TakeWhileIterator<'self, A, T> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
let (_, upper) = self.iter.size_hint();
|
||||
(0, upper) // can't know a lower bound, due to the predicate
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator which skips over `n` elements of `iter`.
|
||||
@ -905,6 +940,21 @@ impl<A, T: Iterator<A>> Iterator<A> for SkipIterator<A, T> {
|
||||
next
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
let (lower, upper) = self.iter.size_hint();
|
||||
|
||||
let lower = if lower >= self.n { lower - self.n } else { 0 };
|
||||
|
||||
let upper = match upper {
|
||||
Some(x) if x >= self.n => Some(x - self.n),
|
||||
Some(_) => Some(0),
|
||||
None => None
|
||||
};
|
||||
|
||||
(lower, upper)
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator which only iterates over the first `n` iterations of `iter`.
|
||||
@ -925,6 +975,20 @@ impl<A, T: Iterator<A>> Iterator<A> for TakeIterator<A, T> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
let (lower, upper) = self.iter.size_hint();
|
||||
|
||||
let lower = cmp::min(lower, self.n);
|
||||
|
||||
let upper = match upper {
|
||||
Some(x) if x < self.n => Some(x),
|
||||
_ => Some(self.n)
|
||||
};
|
||||
|
||||
(lower, upper)
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator to maintain state while iterating another iterator
|
||||
@ -941,6 +1005,12 @@ impl<'self, A, B, T: Iterator<A>, St> Iterator<B> for ScanIterator<'self, A, B,
|
||||
fn next(&mut self) -> Option<B> {
|
||||
self.iter.next().chain(|a| (self.f)(&mut self.state, a))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
let (_, upper) = self.iter.size_hint();
|
||||
(0, upper) // can't know a lower bound, due to the scan function
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator that maps each element to an iterator,
|
||||
@ -1022,6 +1092,11 @@ impl<A: Add<A, A> + Clone> Iterator<A> for Counter<A> {
|
||||
self.state = self.state.add(&self.step); // FIXME: #6050
|
||||
Some(result)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
(uint::max_value, None) // Too bad we can't specify an infinite lower bound
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -1237,6 +1312,43 @@ mod tests {
|
||||
assert_eq!(v.slice(0, 0).iter().transform(|&x| x).min(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iterator_size_hint() {
|
||||
let c = Counter::new(0, 1);
|
||||
let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
let v2 = &[10, 11, 12];
|
||||
let vi = v.iter();
|
||||
|
||||
assert_eq!(c.size_hint(), (uint::max_value, None));
|
||||
assert_eq!(vi.size_hint(), (10, Some(10)));
|
||||
|
||||
assert_eq!(c.take_(5).size_hint(), (5, Some(5)));
|
||||
assert_eq!(c.skip(5).size_hint().second(), None);
|
||||
assert_eq!(c.take_while(|_| false).size_hint(), (0, None));
|
||||
assert_eq!(c.skip_while(|_| false).size_hint(), (0, None));
|
||||
assert_eq!(c.enumerate().size_hint(), (uint::max_value, None));
|
||||
assert_eq!(c.chain_(vi.transform(|&i| i)).size_hint(), (uint::max_value, None));
|
||||
assert_eq!(c.zip(vi).size_hint(), (10, Some(10)));
|
||||
assert_eq!(c.scan(0, |_,_| Some(0)).size_hint(), (0, None));
|
||||
assert_eq!(c.filter(|_| false).size_hint(), (0, None));
|
||||
assert_eq!(c.transform(|_| 0).size_hint(), (uint::max_value, None));
|
||||
assert_eq!(c.filter_map(|_| Some(0)).size_hint(), (0, None));
|
||||
|
||||
assert_eq!(vi.take_(5).size_hint(), (5, Some(5)));
|
||||
assert_eq!(vi.take_(12).size_hint(), (10, Some(10)));
|
||||
assert_eq!(vi.skip(3).size_hint(), (7, Some(7)));
|
||||
assert_eq!(vi.skip(12).size_hint(), (0, Some(0)));
|
||||
assert_eq!(vi.take_while(|_| false).size_hint(), (0, Some(10)));
|
||||
assert_eq!(vi.skip_while(|_| false).size_hint(), (0, Some(10)));
|
||||
assert_eq!(vi.enumerate().size_hint(), (10, Some(10)));
|
||||
assert_eq!(vi.chain_(v2.iter()).size_hint(), (13, Some(13)));
|
||||
assert_eq!(vi.zip(v2.iter()).size_hint(), (3, Some(3)));
|
||||
assert_eq!(vi.scan(0, |_,_| Some(0)).size_hint(), (0, Some(10)));
|
||||
assert_eq!(vi.filter(|_| false).size_hint(), (0, Some(10)));
|
||||
assert_eq!(vi.transform(|i| i+1).size_hint(), (10, Some(10)));
|
||||
assert_eq!(vi.filter_map(|_| Some(0)).size_hint(), (0, Some(10)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_collect() {
|
||||
let a = ~[1, 2, 3, 4, 5];
|
||||
|
@ -2024,14 +2024,14 @@ macro_rules! iterator {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (Option<uint>, Option<uint>) {
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
let diff = if $step > 0 {
|
||||
(self.end as uint) - (self.ptr as uint)
|
||||
} else {
|
||||
(self.ptr as uint) - (self.end as uint)
|
||||
};
|
||||
let exact = Some(diff / size_of::<$elem>());
|
||||
(exact, exact)
|
||||
let exact = diff / size_of::<$elem>();
|
||||
(exact, Some(exact))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2132,7 +2132,7 @@ impl<A, T: Iterator<A>> FromIterator<A, T> for ~[A] {
|
||||
impl<A, T: Iterator<A>> FromIterator<A, T> for ~[A] {
|
||||
pub fn from_iterator(iterator: &mut T) -> ~[A] {
|
||||
let (lower, _) = iterator.size_hint();
|
||||
let mut xs = with_capacity(lower.get_or_zero());
|
||||
let mut xs = with_capacity(lower);
|
||||
for iterator.advance |x| {
|
||||
xs.push(x);
|
||||
}
|
||||
@ -2968,17 +2968,17 @@ mod tests {
|
||||
use iterator::*;
|
||||
let xs = [1, 2, 5, 10, 11];
|
||||
let mut it = xs.iter();
|
||||
assert_eq!(it.size_hint(), (Some(5), Some(5)));
|
||||
assert_eq!(it.size_hint(), (5, Some(5)));
|
||||
assert_eq!(it.next().unwrap(), &1);
|
||||
assert_eq!(it.size_hint(), (Some(4), Some(4)));
|
||||
assert_eq!(it.size_hint(), (4, Some(4)));
|
||||
assert_eq!(it.next().unwrap(), &2);
|
||||
assert_eq!(it.size_hint(), (Some(3), Some(3)));
|
||||
assert_eq!(it.size_hint(), (3, Some(3)));
|
||||
assert_eq!(it.next().unwrap(), &5);
|
||||
assert_eq!(it.size_hint(), (Some(2), Some(2)));
|
||||
assert_eq!(it.size_hint(), (2, Some(2)));
|
||||
assert_eq!(it.next().unwrap(), &10);
|
||||
assert_eq!(it.size_hint(), (Some(1), Some(1)));
|
||||
assert_eq!(it.size_hint(), (1, Some(1)));
|
||||
assert_eq!(it.next().unwrap(), &11);
|
||||
assert_eq!(it.size_hint(), (Some(0), Some(0)));
|
||||
assert_eq!(it.size_hint(), (0, Some(0)));
|
||||
assert!(it.next().is_none());
|
||||
}
|
||||
|
||||
@ -2986,10 +2986,10 @@ mod tests {
|
||||
fn test_iter_size_hints() {
|
||||
use iterator::*;
|
||||
let mut xs = [1, 2, 5, 10, 11];
|
||||
assert_eq!(xs.iter().size_hint(), (Some(5), Some(5)));
|
||||
assert_eq!(xs.rev_iter().size_hint(), (Some(5), Some(5)));
|
||||
assert_eq!(xs.mut_iter().size_hint(), (Some(5), Some(5)));
|
||||
assert_eq!(xs.mut_rev_iter().size_hint(), (Some(5), Some(5)));
|
||||
assert_eq!(xs.iter().size_hint(), (5, Some(5)));
|
||||
assert_eq!(xs.rev_iter().size_hint(), (5, Some(5)));
|
||||
assert_eq!(xs.mut_iter().size_hint(), (5, Some(5)));
|
||||
assert_eq!(xs.mut_rev_iter().size_hint(), (5, Some(5)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -146,4 +146,12 @@ impl<'self, T> Iterator<&'self T> for OptVecIterator<'self, T> {
|
||||
None => None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
match self.iter {
|
||||
Some(ref x) => x.size_hint(),
|
||||
None => (0, Some(0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user