Skip to content

Commit 562626a

Browse files
authored
Rollup merge of rust-lang#48115 - Centril:feature/iterator_flatten, r=alexcrichton
Add Iterator::flatten This adds the trait method `.flatten()` on `Iterator` which flattens one level of nesting from an iterator or (into)iterators. The method `.flat_fmap(f)` is then redefined as `.map(f).flatten()`. The implementation of `Flatten` is essentially that of what it was for `FlatMap` but removing the call to `f` at various places. Hopefully the type alias approach should be OK as was indicated / alluded to by @bluss and @eddyb in rust-lang/rfcs#2306 (comment). cc @scottmcm
2 parents 725856d + 819d57a commit 562626a

File tree

5 files changed

+367
-36
lines changed

5 files changed

+367
-36
lines changed

src/libcore/iter/iterator.rs

+79-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ 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, Fuse};
16+
use super::{Flatten, FlatMap, flatten_compat};
1617
use super::{Inspect, Map, Peekable, Scan, Skip, SkipWhile, StepBy, Take, TakeWhile, Rev};
1718
use super::{Zip, Sum, Product};
1819
use super::{ChainState, FromIterator, ZipImpl};
@@ -997,11 +998,15 @@ pub trait Iterator {
997998
/// an extra layer of indirection. `flat_map()` will remove this extra layer
998999
/// on its own.
9991000
///
1001+
/// You can think of [`flat_map(f)`][flat_map] as the semantic equivalent
1002+
/// of [`map`]ping, and then [`flatten`]ing as in `map(f).flatten()`.
1003+
///
10001004
/// Another way of thinking about `flat_map()`: [`map`]'s closure returns
10011005
/// one item for each element, and `flat_map()`'s closure returns an
10021006
/// iterator for each element.
10031007
///
10041008
/// [`map`]: #method.map
1009+
/// [`flatten`]: #method.flatten
10051010
///
10061011
/// # Examples
10071012
///
@@ -1021,7 +1026,79 @@ pub trait Iterator {
10211026
fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F>
10221027
where Self: Sized, U: IntoIterator, F: FnMut(Self::Item) -> U,
10231028
{
1024-
FlatMap{iter: self, f: f, frontiter: None, backiter: None }
1029+
FlatMap { inner: flatten_compat(self.map(f)) }
1030+
}
1031+
1032+
/// Creates an iterator that flattens nested structure.
1033+
///
1034+
/// This is useful when you have an iterator of iterators or an iterator of
1035+
/// things that can be turned into iterators and you want to remove one
1036+
/// level of indirection.
1037+
///
1038+
/// # Examples
1039+
///
1040+
/// Basic usage:
1041+
///
1042+
/// ```
1043+
/// #![feature(iterator_flatten)]
1044+
///
1045+
/// let data = vec![vec![1, 2, 3, 4], vec![5, 6]];
1046+
/// let flattened = data.into_iter().flatten().collect::<Vec<u8>>();
1047+
/// assert_eq!(flattened, &[1, 2, 3, 4, 5, 6]);
1048+
/// ```
1049+
///
1050+
/// Mapping and then flattening:
1051+
///
1052+
/// ```
1053+
/// #![feature(iterator_flatten)]
1054+
///
1055+
/// let words = ["alpha", "beta", "gamma"];
1056+
///
1057+
/// // chars() returns an iterator
1058+
/// let merged: String = words.iter()
1059+
/// .map(|s| s.chars())
1060+
/// .flatten()
1061+
/// .collect();
1062+
/// assert_eq!(merged, "alphabetagamma");
1063+
/// ```
1064+
///
1065+
/// You can also rewrite this in terms of [`flat_map()`] which is preferable
1066+
/// in this case since that conveys intent clearer:
1067+
///
1068+
/// ```
1069+
/// let words = ["alpha", "beta", "gamma"];
1070+
///
1071+
/// // chars() returns an iterator
1072+
/// let merged: String = words.iter()
1073+
/// .flat_map(|s| s.chars())
1074+
/// .collect();
1075+
/// assert_eq!(merged, "alphabetagamma");
1076+
/// ```
1077+
///
1078+
/// Flattening once only removes one level of nesting:
1079+
///
1080+
/// ```
1081+
/// #![feature(iterator_flatten)]
1082+
///
1083+
/// let d3 = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]];
1084+
///
1085+
/// let d2 = d3.iter().flatten().collect::<Vec<_>>();
1086+
/// assert_eq!(d2, [&[1, 2], &[3, 4], &[5, 6], &[7, 8]]);
1087+
///
1088+
/// let d1 = d3.iter().flatten().flatten().collect::<Vec<_>>();
1089+
/// assert_eq!(d1, [&1, &2, &3, &4, &5, &6, &7, &8]);
1090+
/// ```
1091+
///
1092+
/// Here we see that `flatten()` does not perform a "deep" flatten.
1093+
/// Instead, only one level of nesting is removed. That is, if you
1094+
/// `flatten()` a three-dimensional array the result will be
1095+
/// two-dimensional and not one-dimensional. To get a one-dimensional
1096+
/// structure, you have to `flatten()` again.
1097+
#[inline]
1098+
#[unstable(feature = "iterator_flatten", issue = "48213")]
1099+
fn flatten(self) -> Flatten<Self>
1100+
where Self: Sized, Self::Item: IntoIterator {
1101+
Flatten { inner: flatten_compat(self) }
10251102
}
10261103

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

src/libcore/iter/mod.rs

+179-34
Original file line numberDiff line numberDiff line change
@@ -2410,24 +2410,23 @@ impl<B, I, St, F> Iterator for Scan<I, St, F> where
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)]
24142413
pub struct FlatMap<I, U: IntoIterator, F> {
2415-
iter: I,
2416-
f: F,
2417-
frontiter: Option<U::IntoIter>,
2418-
backiter: Option<U::IntoIter>,
2414+
inner: FlattenCompat<Map<I, F>, <U as IntoIterator>::IntoIter>
2415+
}
2416+
2417+
#[stable(feature = "rust1", since = "1.0.0")]
2418+
impl<I: Clone, U: Clone + IntoIterator, F: Clone> Clone for FlatMap<I, U, F>
2419+
where <U as IntoIterator>::IntoIter: Clone
2420+
{
2421+
fn clone(&self) -> Self { FlatMap { inner: self.inner.clone() } }
24192422
}
24202423

24212424
#[stable(feature = "core_impl_debug", since = "1.9.0")]
24222425
impl<I: fmt::Debug, U: IntoIterator, F> fmt::Debug for FlatMap<I, U, F>
24232426
where U::IntoIter: fmt::Debug
24242427
{
24252428
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()
2429+
f.debug_struct("FlatMap").field("inner", &self.inner).finish()
24312430
}
24322431
}
24332432

@@ -2437,17 +2436,173 @@ impl<I: Iterator, U: IntoIterator, F> Iterator for FlatMap<I, U, F>
24372436
{
24382437
type Item = U::Item;
24392438

2439+
#[inline]
2440+
fn next(&mut self) -> Option<U::Item> { self.inner.next() }
2441+
2442+
#[inline]
2443+
fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
2444+
2445+
#[inline]
2446+
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
2447+
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
2448+
{
2449+
self.inner.try_fold(init, fold)
2450+
}
2451+
2452+
#[inline]
2453+
fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
2454+
where Fold: FnMut(Acc, Self::Item) -> Acc,
2455+
{
2456+
self.inner.fold(init, fold)
2457+
}
2458+
}
2459+
2460+
#[stable(feature = "rust1", since = "1.0.0")]
2461+
impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F>
2462+
where F: FnMut(I::Item) -> U,
2463+
U: IntoIterator,
2464+
U::IntoIter: DoubleEndedIterator
2465+
{
2466+
#[inline]
2467+
fn next_back(&mut self) -> Option<U::Item> { self.inner.next_back() }
2468+
2469+
#[inline]
2470+
fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
2471+
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
2472+
{
2473+
self.inner.try_rfold(init, fold)
2474+
}
2475+
2476+
#[inline]
2477+
fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
2478+
where Fold: FnMut(Acc, Self::Item) -> Acc,
2479+
{
2480+
self.inner.rfold(init, fold)
2481+
}
2482+
}
2483+
2484+
#[unstable(feature = "fused", issue = "35602")]
2485+
impl<I, U, F> FusedIterator for FlatMap<I, U, F>
2486+
where I: FusedIterator, U: IntoIterator, F: FnMut(I::Item) -> U {}
2487+
2488+
/// An iterator that flattens one level of nesting in an iterator of things
2489+
/// that can be turned into iterators.
2490+
///
2491+
/// This `struct` is created by the [`flatten`] method on [`Iterator`]. See its
2492+
/// documentation for more.
2493+
///
2494+
/// [`flatten`]: trait.Iterator.html#method.flatten
2495+
/// [`Iterator`]: trait.Iterator.html
2496+
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
2497+
#[unstable(feature = "iterator_flatten", issue = "48213")]
2498+
pub struct Flatten<I: Iterator>
2499+
where I::Item: IntoIterator {
2500+
inner: FlattenCompat<I, <I::Item as IntoIterator>::IntoIter>,
2501+
}
2502+
2503+
#[unstable(feature = "iterator_flatten", issue = "48213")]
2504+
impl<I, U> fmt::Debug for Flatten<I>
2505+
where I: Iterator + fmt::Debug, U: Iterator + fmt::Debug,
2506+
I::Item: IntoIterator<IntoIter = U, Item = U::Item>,
2507+
{
2508+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2509+
f.debug_struct("Flatten").field("inner", &self.inner).finish()
2510+
}
2511+
}
2512+
2513+
#[unstable(feature = "iterator_flatten", issue = "48213")]
2514+
impl<I, U> Clone for Flatten<I>
2515+
where I: Iterator + Clone, U: Iterator + Clone,
2516+
I::Item: IntoIterator<IntoIter = U, Item = U::Item>,
2517+
{
2518+
fn clone(&self) -> Self { Flatten { inner: self.inner.clone() } }
2519+
}
2520+
2521+
#[unstable(feature = "iterator_flatten", issue = "48213")]
2522+
impl<I, U> Iterator for Flatten<I>
2523+
where I: Iterator, U: Iterator,
2524+
I::Item: IntoIterator<IntoIter = U, Item = U::Item>
2525+
{
2526+
type Item = U::Item;
2527+
2528+
#[inline]
2529+
fn next(&mut self) -> Option<U::Item> { self.inner.next() }
2530+
2531+
#[inline]
2532+
fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
2533+
2534+
#[inline]
2535+
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
2536+
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
2537+
{
2538+
self.inner.try_fold(init, fold)
2539+
}
2540+
2541+
#[inline]
2542+
fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
2543+
where Fold: FnMut(Acc, Self::Item) -> Acc,
2544+
{
2545+
self.inner.fold(init, fold)
2546+
}
2547+
}
2548+
2549+
#[unstable(feature = "iterator_flatten", issue = "48213")]
2550+
impl<I, U> DoubleEndedIterator for Flatten<I>
2551+
where I: DoubleEndedIterator, U: DoubleEndedIterator,
2552+
I::Item: IntoIterator<IntoIter = U, Item = U::Item>
2553+
{
2554+
#[inline]
2555+
fn next_back(&mut self) -> Option<U::Item> { self.inner.next_back() }
2556+
2557+
#[inline]
2558+
fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
2559+
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
2560+
{
2561+
self.inner.try_rfold(init, fold)
2562+
}
2563+
2564+
#[inline]
2565+
fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
2566+
where Fold: FnMut(Acc, Self::Item) -> Acc,
2567+
{
2568+
self.inner.rfold(init, fold)
2569+
}
2570+
}
2571+
2572+
#[unstable(feature = "fused", issue = "35602")]
2573+
impl<I, U> FusedIterator for Flatten<I>
2574+
where I: FusedIterator, U: Iterator,
2575+
I::Item: IntoIterator<IntoIter = U, Item = U::Item> {}
2576+
2577+
/// Adapts an iterator by flattening it, for use in `flatten()` and `flat_map()`.
2578+
fn flatten_compat<I, U>(iter: I) -> FlattenCompat<I, U> {
2579+
FlattenCompat { iter, frontiter: None, backiter: None }
2580+
}
2581+
2582+
/// Real logic of both `Flatten` and `FlatMap` which simply delegate to
2583+
/// this type.
2584+
#[derive(Clone, Debug)]
2585+
struct FlattenCompat<I, U> {
2586+
iter: I,
2587+
frontiter: Option<U>,
2588+
backiter: Option<U>,
2589+
}
2590+
2591+
impl<I, U> Iterator for FlattenCompat<I, U>
2592+
where I: Iterator, U: Iterator,
2593+
I::Item: IntoIterator<IntoIter = U, Item = U::Item>
2594+
{
2595+
type Item = U::Item;
2596+
24402597
#[inline]
24412598
fn next(&mut self) -> Option<U::Item> {
24422599
loop {
24432600
if let Some(ref mut inner) = self.frontiter {
2444-
if let Some(x) = inner.by_ref().next() {
2445-
return Some(x)
2446-
}
2601+
if let elt@Some(_) = inner.next() { return elt }
24472602
}
2448-
match self.iter.next().map(&mut self.f) {
2603+
match self.iter.next() {
24492604
None => return self.backiter.as_mut().and_then(|it| it.next()),
2450-
next => self.frontiter = next.map(IntoIterator::into_iter),
2605+
Some(inner) => self.frontiter = Some(inner.into_iter()),
24512606
}
24522607
}
24532608
}
@@ -2473,10 +2628,9 @@ impl<I: Iterator, U: IntoIterator, F> Iterator for FlatMap<I, U, F>
24732628
self.frontiter = None;
24742629

24752630
{
2476-
let f = &mut self.f;
24772631
let frontiter = &mut self.frontiter;
24782632
init = self.iter.try_fold(init, |acc, x| {
2479-
let mut mid = f(x).into_iter();
2633+
let mut mid = x.into_iter();
24802634
let r = mid.try_fold(acc, &mut fold);
24812635
*frontiter = Some(mid);
24822636
r
@@ -2497,27 +2651,23 @@ impl<I: Iterator, U: IntoIterator, F> Iterator for FlatMap<I, U, F>
24972651
where Fold: FnMut(Acc, Self::Item) -> Acc,
24982652
{
24992653
self.frontiter.into_iter()
2500-
.chain(self.iter.map(self.f).map(U::into_iter))
2654+
.chain(self.iter.map(IntoIterator::into_iter))
25012655
.chain(self.backiter)
25022656
.fold(init, |acc, iter| iter.fold(acc, &mut fold))
25032657
}
25042658
}
25052659

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
2660+
impl<I, U> DoubleEndedIterator for FlattenCompat<I, U>
2661+
where I: DoubleEndedIterator, U: DoubleEndedIterator,
2662+
I::Item: IntoIterator<IntoIter = U, Item = U::Item>
25112663
{
25122664
#[inline]
25132665
fn next_back(&mut self) -> Option<U::Item> {
25142666
loop {
25152667
if let Some(ref mut inner) = self.backiter {
2516-
if let Some(y) = inner.next_back() {
2517-
return Some(y)
2518-
}
2668+
if let elt@Some(_) = inner.next_back() { return elt }
25192669
}
2520-
match self.iter.next_back().map(&mut self.f) {
2670+
match self.iter.next_back() {
25212671
None => return self.frontiter.as_mut().and_then(|it| it.next_back()),
25222672
next => self.backiter = next.map(IntoIterator::into_iter),
25232673
}
@@ -2534,10 +2684,9 @@ impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F> wher
25342684
self.backiter = None;
25352685

25362686
{
2537-
let f = &mut self.f;
25382687
let backiter = &mut self.backiter;
25392688
init = self.iter.try_rfold(init, |acc, x| {
2540-
let mut mid = f(x).into_iter();
2689+
let mut mid = x.into_iter();
25412690
let r = mid.try_rfold(acc, &mut fold);
25422691
*backiter = Some(mid);
25432692
r
@@ -2558,16 +2707,12 @@ impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F> wher
25582707
where Fold: FnMut(Acc, Self::Item) -> Acc,
25592708
{
25602709
self.frontiter.into_iter()
2561-
.chain(self.iter.map(self.f).map(U::into_iter))
2710+
.chain(self.iter.map(IntoIterator::into_iter))
25622711
.chain(self.backiter)
25632712
.rfold(init, |acc, iter| iter.rfold(acc, &mut fold))
25642713
}
25652714
}
25662715

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 {}
2570-
25712716
/// An iterator that yields `None` forever after the underlying iterator
25722717
/// yields `None` once.
25732718
///

0 commit comments

Comments
 (0)