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