Skip to content

Commit 6291702

Browse files
author
blake2-ppc
committed
iterator: Add IteratorUtil::flat_map_ method
flat_map_ produces an iterator that maps each element to an iterator, and yields the elements of the produced iterators. This is the monadic bind :: M a -> (a -> M b) -> M b for iterators. Named just like the vec method, but with a trailing underline until the method resolution bug is resolved.
1 parent dfb7de8 commit 6291702

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed

src/libstd/iterator.rs

+67
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,26 @@ pub trait IteratorUtil<A> {
226226
fn scan<'r, St, B>(self, initial_state: St, f: &'r fn(&mut St, A) -> Option<B>)
227227
-> ScanIterator<'r, A, B, Self, St>;
228228

229+
/// Creates an iterator that maps each element to an iterator,
230+
/// and yields the elements of the produced iterators
231+
///
232+
/// # Example
233+
///
234+
/// ~~~ {.rust}
235+
/// let xs = [2u, 3];
236+
/// let ys = [0u, 1, 0, 1, 2];
237+
/// let mut it = xs.iter().flat_map_(|&x| Counter::new(0u, 1).take_(x));
238+
/// // Check that `it` has the same elements as `ys`
239+
/// let mut i = 0;
240+
/// for it.advance |x: uint| {
241+
/// assert_eq!(x, ys[i]);
242+
/// i += 1;
243+
/// }
244+
/// ~~~
245+
// FIXME: #5898: should be called `flat_map`
246+
fn flat_map_<'r, B, U: Iterator<B>>(self, f: &'r fn(A) -> U)
247+
-> FlatMapIterator<'r, A, B, Self, U>;
248+
229249
/// An adaptation of an external iterator to the for-loop protocol of rust.
230250
///
231251
/// # Example
@@ -397,6 +417,12 @@ impl<A, T: Iterator<A>> IteratorUtil<A> for T {
397417
ScanIterator{iter: self, f: f, state: initial_state}
398418
}
399419

420+
#[inline]
421+
fn flat_map_<'r, B, U: Iterator<B>>(self, f: &'r fn(A) -> U)
422+
-> FlatMapIterator<'r, A, B, T, U> {
423+
FlatMapIterator{iter: self, f: f, subiter: None }
424+
}
425+
400426
/// A shim implementing the `for` loop iteration protocol for iterator objects
401427
#[inline]
402428
fn advance(&mut self, f: &fn(A) -> bool) -> bool {
@@ -873,6 +899,34 @@ impl<'self, A, B, T: Iterator<A>, St> Iterator<B> for ScanIterator<'self, A, B,
873899
}
874900
}
875901

902+
/// An iterator that maps each element to an iterator,
903+
/// and yields the elements of the produced iterators
904+
///
905+
// FIXME #6967: Dummy B parameter to get around type inference bug
906+
pub struct FlatMapIterator<'self, A, B, T, U> {
907+
priv iter: T,
908+
priv f: &'self fn(A) -> U,
909+
priv subiter: Option<U>,
910+
}
911+
912+
impl<'self, A, T: Iterator<A>, B, U: Iterator<B>> Iterator<B> for
913+
FlatMapIterator<'self, A, B, T, U> {
914+
#[inline]
915+
fn next(&mut self) -> Option<B> {
916+
loop {
917+
for self.subiter.mut_iter().advance |inner| {
918+
for inner.advance |x| {
919+
return Some(x)
920+
}
921+
}
922+
match self.iter.next().map_consume(self.f) {
923+
None => return None,
924+
next => self.subiter = next,
925+
}
926+
}
927+
}
928+
}
929+
876930
/// An iterator which just modifies the contained state throughout iteration.
877931
pub struct UnfoldrIterator<'self, A, St> {
878932
priv f: &'self fn(&mut St) -> Option<A>,
@@ -1051,6 +1105,19 @@ mod tests {
10511105
assert_eq!(i, ys.len());
10521106
}
10531107

1108+
#[test]
1109+
fn test_iterator_flat_map() {
1110+
let xs = [0u, 3, 6];
1111+
let ys = [0u, 1, 2, 3, 4, 5, 6, 7, 8];
1112+
let mut it = xs.iter().flat_map_(|&x| Counter::new(x, 1).take_(3));
1113+
let mut i = 0;
1114+
for it.advance |x: uint| {
1115+
assert_eq!(x, ys[i]);
1116+
i += 1;
1117+
}
1118+
assert_eq!(i, ys.len());
1119+
}
1120+
10541121
#[test]
10551122
fn test_unfoldr() {
10561123
fn count(st: &mut uint) -> Option<uint> {

0 commit comments

Comments
 (0)