core: Refactor iterators
Simplifying the code of methods: nth, fold, rposition and iterators: Filter, FilterMap, SkipWhile Adding basic benchmarks
This commit is contained in:
parent
032d5c1dcd
commit
a55149b84e
@ -481,13 +481,11 @@ pub trait Iterator<A> {
|
||||
/// ```
|
||||
#[inline]
|
||||
fn nth(&mut self, mut n: uint) -> Option<A> {
|
||||
loop {
|
||||
match self.next() {
|
||||
Some(x) => if n == 0 { return Some(x) },
|
||||
None => return None
|
||||
}
|
||||
for x in *self {
|
||||
if n == 0 { return Some(x) }
|
||||
n -= 1;
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Loops through the entire iterator, returning the last element of the
|
||||
@ -518,11 +516,8 @@ pub trait Iterator<A> {
|
||||
#[inline]
|
||||
fn fold<B>(&mut self, init: B, f: |B, A| -> B) -> B {
|
||||
let mut accum = init;
|
||||
loop {
|
||||
match self.next() {
|
||||
Some(x) => { accum = f(accum, x); }
|
||||
None => { break; }
|
||||
}
|
||||
for x in *self {
|
||||
accum = f(accum, x);
|
||||
}
|
||||
accum
|
||||
}
|
||||
@ -720,21 +715,10 @@ pub trait ExactSize<A> : DoubleEndedIterator<A> {
|
||||
/// If no element matches, None is returned.
|
||||
#[inline]
|
||||
fn rposition(&mut self, predicate: |A| -> bool) -> Option<uint> {
|
||||
let (lower, upper) = self.size_hint();
|
||||
assert!(upper == Some(lower));
|
||||
let mut i = lower;
|
||||
loop {
|
||||
match self.next_back() {
|
||||
None => break,
|
||||
Some(x) => {
|
||||
i = match i.checked_sub(&1) {
|
||||
Some(x) => x,
|
||||
None => fail!("rposition: incorrect ExactSize")
|
||||
};
|
||||
if predicate(x) {
|
||||
return Some(i)
|
||||
}
|
||||
}
|
||||
let len = self.len();
|
||||
for i in range(0, len).rev() {
|
||||
if predicate(self.next_back().expect("rposition: incorrect ExactSize")) {
|
||||
return Some(i);
|
||||
}
|
||||
}
|
||||
None
|
||||
@ -744,7 +728,7 @@ pub trait ExactSize<A> : DoubleEndedIterator<A> {
|
||||
/// Return the exact length of the iterator.
|
||||
fn len(&self) -> uint {
|
||||
let (lower, upper) = self.size_hint();
|
||||
assert!(upper == Some(lower));
|
||||
assert_eq!(upper, Some(lower));
|
||||
lower
|
||||
}
|
||||
}
|
||||
@ -1330,18 +1314,12 @@ impl<'a, A, T: Iterator<A>> Iterator<A> for Filter<'a, A, T> {
|
||||
impl<'a, A, T: DoubleEndedIterator<A>> DoubleEndedIterator<A> for Filter<'a, A, T> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<A> {
|
||||
loop {
|
||||
match self.iter.next_back() {
|
||||
None => return None,
|
||||
Some(x) => {
|
||||
if (self.predicate)(&x) {
|
||||
return Some(x);
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
for x in self.iter.by_ref().rev() {
|
||||
if (self.predicate)(&x) {
|
||||
return Some(x);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@ -1375,17 +1353,13 @@ impl<'a, A, B, T: DoubleEndedIterator<A>> DoubleEndedIterator<B>
|
||||
for FilterMap<'a, A, B, T> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<B> {
|
||||
loop {
|
||||
match self.iter.next_back() {
|
||||
None => return None,
|
||||
Some(x) => {
|
||||
match (self.f)(x) {
|
||||
Some(y) => return Some(y),
|
||||
None => ()
|
||||
}
|
||||
}
|
||||
for x in self.iter.by_ref().rev() {
|
||||
match (self.f)(x) {
|
||||
Some(y) => return Some(y),
|
||||
None => ()
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@ -1507,25 +1481,13 @@ pub struct SkipWhile<'a, A, T> {
|
||||
impl<'a, A, T: Iterator<A>> Iterator<A> for SkipWhile<'a, A, T> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> {
|
||||
let mut next = self.iter.next();
|
||||
if self.flag {
|
||||
next
|
||||
} else {
|
||||
loop {
|
||||
match next {
|
||||
Some(x) => {
|
||||
if (self.predicate)(&x) {
|
||||
next = self.iter.next();
|
||||
continue
|
||||
} else {
|
||||
self.flag = true;
|
||||
return Some(x)
|
||||
}
|
||||
}
|
||||
None => return None
|
||||
}
|
||||
for x in self.iter {
|
||||
if self.flag || !(self.predicate)(&x) {
|
||||
self.flag = true;
|
||||
return Some(x);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -14,6 +14,8 @@ use core::uint;
|
||||
use core::cmp;
|
||||
use core::num;
|
||||
|
||||
use test::Bencher;
|
||||
|
||||
#[test]
|
||||
fn test_lt() {
|
||||
let empty: [int, ..0] = [];
|
||||
@ -270,6 +272,7 @@ fn test_iterator_nth() {
|
||||
for i in range(0u, v.len()) {
|
||||
assert_eq!(v.iter().nth(i).unwrap(), &v[i]);
|
||||
}
|
||||
assert_eq!(v.iter().nth(v.len()), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -842,3 +845,31 @@ fn test_iterate() {
|
||||
assert_eq!(it.next(), Some(4u));
|
||||
assert_eq!(it.next(), Some(8u));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_rposition(b: &mut Bencher) {
|
||||
let it: Vec<uint> = range(0u, 300).collect();
|
||||
b.iter(|| {
|
||||
it.iter().rposition(|&x| x <= 150);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_skip_while(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let it = range(0u, 100);
|
||||
let mut sum = 0;
|
||||
it.skip_while(|&x| { sum += x; sum < 4000 }).all(|_| true);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_multiple_take(b: &mut Bencher) {
|
||||
let mut it = range(0u, 42).cycle();
|
||||
b.iter(|| {
|
||||
let n = it.next().unwrap();
|
||||
for m in range(0u, n) {
|
||||
it.take(it.next().unwrap()).all(|_| true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user