Skip to content

Commit

Permalink
auto merge of #5973 : huonw/rust/core-iterator-scan-consumers, r=thes…
Browse files Browse the repository at this point in the history
…tinger

@thestinger r?

~~The 2 `_unlimited` functions are marked `unsafe` since they may not terminate.~~

The `state` fields of the `Unfoldr` and `Scan` iterators are public, since being able to access the final state after the iteration has finished seems reasonable/possibly useful.

~~Lastly, I converted the tests to use `.to_vec`, which halves the amount of code for them, but it means that a `.transform(|x| *x)` call is required on each iterator.~~ 

(removed the 2 commits with `to_vec` and `foldl`.)
  • Loading branch information
bors committed Apr 20, 2013
2 parents f2b0ef1 + a0c2949 commit 2b09267
Showing 1 changed file with 43 additions and 2 deletions.
45 changes: 43 additions & 2 deletions src/libcore/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ pub trait IteratorUtil<A> {
fn take_while<'r>(self, predicate: &'r fn(&A) -> bool) -> TakeWhileIterator<'r, A, Self>;
fn skip(self, n: uint) -> SkipIterator<Self>;
fn take(self, n: uint) -> TakeIterator<Self>;
fn scan<'r, St, B>(self, initial_state: St, f: &'r fn(&mut St, A) -> Option<B>)
-> ScanIterator<'r, A, B, Self, St>;
fn advance(&mut self, f: &fn(A) -> bool);
}

Expand Down Expand Up @@ -93,6 +95,12 @@ impl<A, T: Iterator<A>> IteratorUtil<A> for T {
TakeIterator{iter: self, n: n}
}

#[inline(always)]
fn scan<'r, St, B>(self, initial_state: St, f: &'r fn(&mut St, A) -> Option<B>)
-> ScanIterator<'r, A, B, T, St> {
ScanIterator{iter: self, f: f, state: initial_state}
}

/// A shim implementing the `for` loop iteration protocol for iterator objects
#[inline]
fn advance(&mut self, f: &fn(A) -> bool) {
Expand Down Expand Up @@ -306,12 +314,13 @@ impl<A, T: Iterator<A>> Iterator<A> for TakeIterator<T> {

pub struct UnfoldrIterator<'self, A, St> {
priv f: &'self fn(&mut St) -> Option<A>,
priv state: St
state: St
}

pub impl<'self, A, St> UnfoldrIterator<'self, A, St> {
#[inline]
fn new(f: &'self fn(&mut St) -> Option<A>, initial_state: St) -> UnfoldrIterator<'self, A, St> {
fn new(f: &'self fn(&mut St) -> Option<A>, initial_state: St)
-> UnfoldrIterator<'self, A, St> {
UnfoldrIterator {
f: f,
state: initial_state
Expand All @@ -326,6 +335,19 @@ impl<'self, A, St> Iterator<A> for UnfoldrIterator<'self, A, St> {
}
}

pub struct ScanIterator<'self, A, B, T, St> {
priv iter: T,
priv f: &'self fn(&mut St, A) -> Option<B>,
state: St
}

impl<'self, A, B, T: Iterator<A>, St> Iterator<B> for ScanIterator<'self, A, B, T, St> {
#[inline]
fn next(&mut self) -> Option<B> {
self.iter.next().chain(|a| (self.f)(&mut self.state, a))
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -406,6 +428,25 @@ mod tests {
assert_eq!(i, ys.len());
}

#[test]
fn test_iterator_scan() {
// test the type inference
fn add(old: &mut int, new: &uint) -> Option<float> {
*old += *new as int;
Some(*old as float)
}
let xs = [0u, 1, 2, 3, 4];
let ys = [0f, 1f, 3f, 6f, 10f];

let mut it = xs.iter().scan(0, add);
let mut i = 0;
for it.advance |x| {
assert_eq!(x, ys[i]);
i += 1;
}
assert_eq!(i, ys.len());
}

#[test]
fn test_unfoldr() {
fn count(st: &mut uint) -> Option<uint> {
Expand Down

0 comments on commit 2b09267

Please sign in to comment.