Skip to content

Commit 6af23f9

Browse files
committed
add Iterator::flatten and redefine flat_map(f) in terms of map(f).flatten()
1 parent 27a046e commit 6af23f9

File tree

4 files changed

+84
-47
lines changed

4 files changed

+84
-47
lines changed

src/libcore/iter/iterator.rs

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use cmp::Ordering;
1212
use ops::Try;
1313

1414
use super::{AlwaysOk, LoopState};
15-
use super::{Chain, Cycle, Cloned, Enumerate, Filter, FilterMap, FlatMap, Fuse};
15+
use super::{Chain, Cycle, Cloned, Enumerate, Filter, FilterMap, Flatten, FlatMap, Fuse};
1616
use super::{Inspect, Map, Peekable, Scan, Skip, SkipWhile, StepBy, Take, TakeWhile, Rev};
1717
use super::{Zip, Sum, Product};
1818
use super::{ChainState, FromIterator, ZipImpl};
@@ -997,11 +997,15 @@ pub trait Iterator {
997997
/// an extra layer of indirection. `flat_map()` will remove this extra layer
998998
/// on its own.
999999
///
1000+
/// You can think of [`flat_map(f)`][flat_map] as the equivalent of
1001+
/// [`map`]ping, and then [`flatten`]ing as in `map(f).flatten()`.
1002+
///
10001003
/// Another way of thinking about `flat_map()`: [`map`]'s closure returns
10011004
/// one item for each element, and `flat_map()`'s closure returns an
10021005
/// iterator for each element.
10031006
///
10041007
/// [`map`]: #method.map
1008+
/// [`flatten`]: #method.flatten
10051009
///
10061010
/// # Examples
10071011
///
@@ -1021,7 +1025,46 @@ pub trait Iterator {
10211025
fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F>
10221026
where Self: Sized, U: IntoIterator, F: FnMut(Self::Item) -> U,
10231027
{
1024-
FlatMap{iter: self, f: f, frontiter: None, backiter: None }
1028+
self.map(f).flatten()
1029+
}
1030+
1031+
/// Creates an iterator that flattens nested structure.
1032+
///
1033+
/// This is useful when you have an iterator of iterators or an iterator of
1034+
/// things that can be turned into iterators and you want to remove one
1035+
/// level of indirection.
1036+
///
1037+
/// # Examples
1038+
///
1039+
/// Basic usage:
1040+
///
1041+
/// ```
1042+
/// #![feature(iterator_flatten)]
1043+
///
1044+
/// let data = vec![vec![1, 2, 3, 4], vec![5, 6]];
1045+
/// let flattened = data.into_iter().flatten().collect::<Vec<u8>>();
1046+
/// assert_eq!(flattened, &[1, 2, 3, 4, 5, 6]);
1047+
/// ```
1048+
///
1049+
/// Mapping and then flattening:
1050+
///
1051+
/// ```
1052+
/// #![feature(iterator_flatten)]
1053+
///
1054+
/// let words = ["alpha", "beta", "gamma"];
1055+
///
1056+
/// // chars() returns an iterator
1057+
/// let merged: String = words.iter()
1058+
/// .map(|s| s.chars())
1059+
/// .flatten()
1060+
/// .collect();
1061+
/// assert_eq!(merged, "alphabetagamma");
1062+
/// ```
1063+
#[inline]
1064+
#[unstable(feature = "iterator_flatten", issue = "0")]
1065+
fn flatten(self) -> Flatten<Self, <Self::Item as IntoIterator>::IntoIter>
1066+
where Self: Sized, Self::Item: IntoIterator {
1067+
Flatten { iter: self, frontiter: None, backiter: None }
10251068
}
10261069

10271070
/// Creates an iterator which ends after the first [`None`].

src/libcore/iter/mod.rs

Lines changed: 36 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2403,51 +2403,47 @@ impl<B, I, St, F> Iterator for Scan<I, St, F> where
24032403
/// An iterator that maps each element to an iterator, and yields the elements
24042404
/// of the produced iterators.
24052405
///
2406-
/// This `struct` is created by the [`flat_map`] method on [`Iterator`]. See its
2406+
/// This `type` is created by the [`flat_map`] method on [`Iterator`]. See its
24072407
/// documentation for more.
24082408
///
24092409
/// [`flat_map`]: trait.Iterator.html#method.flat_map
24102410
/// [`Iterator`]: trait.Iterator.html
24112411
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
24122412
#[stable(feature = "rust1", since = "1.0.0")]
2413-
#[derive(Clone)]
2414-
pub struct FlatMap<I, U: IntoIterator, F> {
2415-
iter: I,
2416-
f: F,
2417-
frontiter: Option<U::IntoIter>,
2418-
backiter: Option<U::IntoIter>,
2419-
}
2413+
type FlatMap<I, U, F> = Flatten<Map<I, F>, <U as IntoIterator>::IntoIter>;
24202414

2421-
#[stable(feature = "core_impl_debug", since = "1.9.0")]
2422-
impl<I: fmt::Debug, U: IntoIterator, F> fmt::Debug for FlatMap<I, U, F>
2423-
where U::IntoIter: fmt::Debug
2424-
{
2425-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2426-
f.debug_struct("FlatMap")
2427-
.field("iter", &self.iter)
2428-
.field("frontiter", &self.frontiter)
2429-
.field("backiter", &self.backiter)
2430-
.finish()
2431-
}
2415+
/// An iterator that flattens one level of nesting in an iterator of things
2416+
/// that can be turned into iterators.
2417+
///
2418+
/// This `struct` is created by the [`flatten`] method on [`Iterator`]. See its
2419+
/// documentation for more.
2420+
///
2421+
/// [`flatten`]: trait.Iterator.html#method.flatten
2422+
/// [`Iterator`]: trait.Iterator.html
2423+
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
2424+
#[unstable(feature = "iterator_flatten", issue = "0")]
2425+
#[derive(Clone, Debug)]
2426+
pub struct Flatten<I, U> {
2427+
iter: I,
2428+
frontiter: Option<U>,
2429+
backiter: Option<U>,
24322430
}
24332431

2434-
#[stable(feature = "rust1", since = "1.0.0")]
2435-
impl<I: Iterator, U: IntoIterator, F> Iterator for FlatMap<I, U, F>
2436-
where F: FnMut(I::Item) -> U,
2432+
#[unstable(feature = "iterator_flatten", issue = "0")]
2433+
impl<I: Iterator, U: Iterator> Iterator for Flatten<I, U>
2434+
where I::Item: IntoIterator<IntoIter = U, Item = U::Item>
24372435
{
24382436
type Item = U::Item;
24392437

24402438
#[inline]
24412439
fn next(&mut self) -> Option<U::Item> {
24422440
loop {
24432441
if let Some(ref mut inner) = self.frontiter {
2444-
if let Some(x) = inner.by_ref().next() {
2445-
return Some(x)
2446-
}
2442+
if let elt@Some(_) = inner.next() { return elt }
24472443
}
2448-
match self.iter.next().map(&mut self.f) {
2444+
match self.iter.next() {
24492445
None => return self.backiter.as_mut().and_then(|it| it.next()),
2450-
next => self.frontiter = next.map(IntoIterator::into_iter),
2446+
Some(inner) => self.frontiter = Some(inner.into_iter()),
24512447
}
24522448
}
24532449
}
@@ -2473,10 +2469,9 @@ impl<I: Iterator, U: IntoIterator, F> Iterator for FlatMap<I, U, F>
24732469
self.frontiter = None;
24742470

24752471
{
2476-
let f = &mut self.f;
24772472
let frontiter = &mut self.frontiter;
24782473
init = self.iter.try_fold(init, |acc, x| {
2479-
let mut mid = f(x).into_iter();
2474+
let mut mid = x.into_iter();
24802475
let r = mid.try_fold(acc, &mut fold);
24812476
*frontiter = Some(mid);
24822477
r
@@ -2497,27 +2492,24 @@ impl<I: Iterator, U: IntoIterator, F> Iterator for FlatMap<I, U, F>
24972492
where Fold: FnMut(Acc, Self::Item) -> Acc,
24982493
{
24992494
self.frontiter.into_iter()
2500-
.chain(self.iter.map(self.f).map(U::into_iter))
2495+
.chain(self.iter.map(IntoIterator::into_iter))
25012496
.chain(self.backiter)
25022497
.fold(init, |acc, iter| iter.fold(acc, &mut fold))
25032498
}
25042499
}
25052500

2506-
#[stable(feature = "rust1", since = "1.0.0")]
2507-
impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F> where
2508-
F: FnMut(I::Item) -> U,
2509-
U: IntoIterator,
2510-
U::IntoIter: DoubleEndedIterator
2501+
#[unstable(feature = "iterator_flatten", issue = "0")]
2502+
impl<I, U> DoubleEndedIterator for Flatten<I, U>
2503+
where I: DoubleEndedIterator, U: DoubleEndedIterator,
2504+
I::Item: IntoIterator<IntoIter = U, Item = U::Item>
25112505
{
25122506
#[inline]
25132507
fn next_back(&mut self) -> Option<U::Item> {
25142508
loop {
25152509
if let Some(ref mut inner) = self.backiter {
2516-
if let Some(y) = inner.next_back() {
2517-
return Some(y)
2518-
}
2510+
if let elt@Some(_) = inner.next_back() { return elt }
25192511
}
2520-
match self.iter.next_back().map(&mut self.f) {
2512+
match self.iter.next_back() {
25212513
None => return self.frontiter.as_mut().and_then(|it| it.next_back()),
25222514
next => self.backiter = next.map(IntoIterator::into_iter),
25232515
}
@@ -2534,10 +2526,9 @@ impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F> wher
25342526
self.backiter = None;
25352527

25362528
{
2537-
let f = &mut self.f;
25382529
let backiter = &mut self.backiter;
25392530
init = self.iter.try_rfold(init, |acc, x| {
2540-
let mut mid = f(x).into_iter();
2531+
let mut mid = x.into_iter();
25412532
let r = mid.try_rfold(acc, &mut fold);
25422533
*backiter = Some(mid);
25432534
r
@@ -2558,15 +2549,15 @@ impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F> wher
25582549
where Fold: FnMut(Acc, Self::Item) -> Acc,
25592550
{
25602551
self.frontiter.into_iter()
2561-
.chain(self.iter.map(self.f).map(U::into_iter))
2552+
.chain(self.iter.map(IntoIterator::into_iter))
25622553
.chain(self.backiter)
25632554
.rfold(init, |acc, iter| iter.rfold(acc, &mut fold))
25642555
}
25652556
}
25662557

2567-
#[unstable(feature = "fused", issue = "35602")]
2568-
impl<I, U, F> FusedIterator for FlatMap<I, U, F>
2569-
where I: FusedIterator, U: IntoIterator, F: FnMut(I::Item) -> U {}
2558+
#[unstable(feature = "fused", issue = "0")]
2559+
impl<I: FusedIterator, U: Iterator> FusedIterator for Flatten<I, U>
2560+
where I::Item: IntoIterator<IntoIter = U, Item = U::Item> {}
25702561

25712562
/// An iterator that yields `None` forever after the underlying iterator
25722563
/// yields `None` once.

src/libcore/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
#![feature(doc_spotlight)]
9494
#![feature(rustc_const_unstable)]
9595
#![feature(iterator_repeat_with)]
96+
#![feature(iterator_flatten)]
9697

9798
#[prelude_import]
9899
#[allow(unused)]

src/libcore/tests/iter.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,8 @@ fn test_iterator_scan() {
836836
assert_eq!(i, ys.len());
837837
}
838838

839+
// Note: We test flatten() by testing flat_map().
840+
839841
#[test]
840842
fn test_iterator_flat_map() {
841843
let xs = [0, 3, 6];

0 commit comments

Comments
 (0)