Skip to content

Commit b9308d1

Browse files
committed
auto merge of #16225 : pczarn/rust/iter-refactoring, r=kballard
Simplifying the code of methods: `nth`, `fold`, `rposition`, and iterators: `Filter`, `FilterMap`, `SkipWhile`. ``` before test iter::bench_multiple_take ... bench: 15 ns/iter (+/- 0) test iter::bench_rposition ... bench: 349 ns/iter (+/- 94) test iter::bench_skip_while ... bench: 158 ns/iter (+/- 6) after test iter::bench_multiple_take ... bench: 15 ns/iter (+/- 0) test iter::bench_rposition ... bench: 314 ns/iter (+/- 2) test iter::bench_skip_while ... bench: 107 ns/iter (+/- 0) ``` @koalazen has the code for `Skip`. Once #16011 is fixed, `min_max` could use a for loop.
2 parents 51e19e7 + a55149b commit b9308d1

File tree

2 files changed

+55
-62
lines changed

2 files changed

+55
-62
lines changed

src/libcore/iter.rs

+24-62
Original file line numberDiff line numberDiff line change
@@ -481,13 +481,11 @@ pub trait Iterator<A> {
481481
/// ```
482482
#[inline]
483483
fn nth(&mut self, mut n: uint) -> Option<A> {
484-
loop {
485-
match self.next() {
486-
Some(x) => if n == 0 { return Some(x) },
487-
None => return None
488-
}
484+
for x in *self {
485+
if n == 0 { return Some(x) }
489486
n -= 1;
490487
}
488+
None
491489
}
492490

493491
/// Loops through the entire iterator, returning the last element of the
@@ -518,11 +516,8 @@ pub trait Iterator<A> {
518516
#[inline]
519517
fn fold<B>(&mut self, init: B, f: |B, A| -> B) -> B {
520518
let mut accum = init;
521-
loop {
522-
match self.next() {
523-
Some(x) => { accum = f(accum, x); }
524-
None => { break; }
525-
}
519+
for x in *self {
520+
accum = f(accum, x);
526521
}
527522
accum
528523
}
@@ -720,21 +715,10 @@ pub trait ExactSize<A> : DoubleEndedIterator<A> {
720715
/// If no element matches, None is returned.
721716
#[inline]
722717
fn rposition(&mut self, predicate: |A| -> bool) -> Option<uint> {
723-
let (lower, upper) = self.size_hint();
724-
assert!(upper == Some(lower));
725-
let mut i = lower;
726-
loop {
727-
match self.next_back() {
728-
None => break,
729-
Some(x) => {
730-
i = match i.checked_sub(&1) {
731-
Some(x) => x,
732-
None => fail!("rposition: incorrect ExactSize")
733-
};
734-
if predicate(x) {
735-
return Some(i)
736-
}
737-
}
718+
let len = self.len();
719+
for i in range(0, len).rev() {
720+
if predicate(self.next_back().expect("rposition: incorrect ExactSize")) {
721+
return Some(i);
738722
}
739723
}
740724
None
@@ -744,7 +728,7 @@ pub trait ExactSize<A> : DoubleEndedIterator<A> {
744728
/// Return the exact length of the iterator.
745729
fn len(&self) -> uint {
746730
let (lower, upper) = self.size_hint();
747-
assert!(upper == Some(lower));
731+
assert_eq!(upper, Some(lower));
748732
lower
749733
}
750734
}
@@ -1330,18 +1314,12 @@ impl<'a, A, T: Iterator<A>> Iterator<A> for Filter<'a, A, T> {
13301314
impl<'a, A, T: DoubleEndedIterator<A>> DoubleEndedIterator<A> for Filter<'a, A, T> {
13311315
#[inline]
13321316
fn next_back(&mut self) -> Option<A> {
1333-
loop {
1334-
match self.iter.next_back() {
1335-
None => return None,
1336-
Some(x) => {
1337-
if (self.predicate)(&x) {
1338-
return Some(x);
1339-
} else {
1340-
continue
1341-
}
1342-
}
1317+
for x in self.iter.by_ref().rev() {
1318+
if (self.predicate)(&x) {
1319+
return Some(x);
13431320
}
13441321
}
1322+
None
13451323
}
13461324
}
13471325

@@ -1375,17 +1353,13 @@ impl<'a, A, B, T: DoubleEndedIterator<A>> DoubleEndedIterator<B>
13751353
for FilterMap<'a, A, B, T> {
13761354
#[inline]
13771355
fn next_back(&mut self) -> Option<B> {
1378-
loop {
1379-
match self.iter.next_back() {
1380-
None => return None,
1381-
Some(x) => {
1382-
match (self.f)(x) {
1383-
Some(y) => return Some(y),
1384-
None => ()
1385-
}
1386-
}
1356+
for x in self.iter.by_ref().rev() {
1357+
match (self.f)(x) {
1358+
Some(y) => return Some(y),
1359+
None => ()
13871360
}
13881361
}
1362+
None
13891363
}
13901364
}
13911365

@@ -1507,25 +1481,13 @@ pub struct SkipWhile<'a, A, T> {
15071481
impl<'a, A, T: Iterator<A>> Iterator<A> for SkipWhile<'a, A, T> {
15081482
#[inline]
15091483
fn next(&mut self) -> Option<A> {
1510-
let mut next = self.iter.next();
1511-
if self.flag {
1512-
next
1513-
} else {
1514-
loop {
1515-
match next {
1516-
Some(x) => {
1517-
if (self.predicate)(&x) {
1518-
next = self.iter.next();
1519-
continue
1520-
} else {
1521-
self.flag = true;
1522-
return Some(x)
1523-
}
1524-
}
1525-
None => return None
1526-
}
1484+
for x in self.iter {
1485+
if self.flag || !(self.predicate)(&x) {
1486+
self.flag = true;
1487+
return Some(x);
15271488
}
15281489
}
1490+
None
15291491
}
15301492

15311493
#[inline]

src/libcoretest/iter.rs

+31
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ use core::uint;
1414
use core::cmp;
1515
use core::num;
1616

17+
use test::Bencher;
18+
1719
#[test]
1820
fn test_lt() {
1921
let empty: [int, ..0] = [];
@@ -270,6 +272,7 @@ fn test_iterator_nth() {
270272
for i in range(0u, v.len()) {
271273
assert_eq!(v.iter().nth(i).unwrap(), &v[i]);
272274
}
275+
assert_eq!(v.iter().nth(v.len()), None);
273276
}
274277

275278
#[test]
@@ -842,3 +845,31 @@ fn test_iterate() {
842845
assert_eq!(it.next(), Some(4u));
843846
assert_eq!(it.next(), Some(8u));
844847
}
848+
849+
#[bench]
850+
fn bench_rposition(b: &mut Bencher) {
851+
let it: Vec<uint> = range(0u, 300).collect();
852+
b.iter(|| {
853+
it.iter().rposition(|&x| x <= 150);
854+
});
855+
}
856+
857+
#[bench]
858+
fn bench_skip_while(b: &mut Bencher) {
859+
b.iter(|| {
860+
let it = range(0u, 100);
861+
let mut sum = 0;
862+
it.skip_while(|&x| { sum += x; sum < 4000 }).all(|_| true);
863+
});
864+
}
865+
866+
#[bench]
867+
fn bench_multiple_take(b: &mut Bencher) {
868+
let mut it = range(0u, 42).cycle();
869+
b.iter(|| {
870+
let n = it.next().unwrap();
871+
for m in range(0u, n) {
872+
it.take(it.next().unwrap()).all(|_| true);
873+
}
874+
});
875+
}

0 commit comments

Comments
 (0)