diff options
| author | kennytm <kennytm@gmail.com> | 2018-02-14 16:14:42 +0800 |
|---|---|---|
| committer | kennytm <kennytm@gmail.com> | 2018-02-14 18:25:22 +0800 |
| commit | bebd2fbfc836f871721057766a90775efa86e6a2 (patch) | |
| tree | 95c390683b7b3bc02ce8f7741ad131fcf381f875 /src/libcore/iter | |
| parent | dcb15269f676f5188f048d4ba014c402a1378086 (diff) | |
| parent | db13296b6fd6b68ab06055bdcb9a22078b11de6a (diff) | |
Rollup merge of #48156 - Centril:feature/iterator_repeat_with, r=alexcrichton
Add std/core::iter::repeat_with Adds an iterator primitive `repeat_with` which is the "lazy" version of `repeat` but also more flexible since you can build up state with the `FnMut`. The design is mostly taken from `repeat`. r? @rust-lang/libs cc @withoutboats, @scottmcm
Diffstat (limited to 'src/libcore/iter')
| -rw-r--r-- | src/libcore/iter/mod.rs | 2 | ||||
| -rw-r--r-- | src/libcore/iter/sources.rs | 115 |
2 files changed, 117 insertions, 0 deletions
diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 29b62c901f3..d929d1d65a9 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -333,6 +333,8 @@ pub use self::range::Step; #[stable(feature = "rust1", since = "1.0.0")] pub use self::sources::{Repeat, repeat}; +#[unstable(feature = "iterator_repeat_with", issue = "48169")] +pub use self::sources::{RepeatWith, repeat_with}; #[stable(feature = "iter_empty", since = "1.2.0")] pub use self::sources::{Empty, empty}; #[stable(feature = "iter_once", since = "1.2.0")] diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs index b05a893e661..3e9d799c089 100644 --- a/src/libcore/iter/sources.rs +++ b/src/libcore/iter/sources.rs @@ -57,6 +57,12 @@ unsafe impl<A: Clone> TrustedLen for Repeat<A> {} /// /// [`take`]: trait.Iterator.html#method.take /// +/// If the element type of the iterator you need does not implement `Clone`, +/// or if you do not want to keep the repeated element in memory, you can +/// instead use the [`repeat_with`] function. +/// +/// [`repeat_with`]: fn.repeat_with.html +/// /// # Examples /// /// Basic usage: @@ -99,6 +105,115 @@ pub fn repeat<T: Clone>(elt: T) -> Repeat<T> { Repeat{element: elt} } +/// An iterator that repeats elements of type `A` endlessly by +/// applying the provided closure `F: FnMut() -> A`. +/// +/// This `struct` is created by the [`repeat_with`] function. +/// See its documentation for more. +/// +/// [`repeat_with`]: fn.repeat_with.html +#[derive(Copy, Clone, Debug)] +#[unstable(feature = "iterator_repeat_with", issue = "48169")] +pub struct RepeatWith<F> { + repeater: F +} + +#[unstable(feature = "iterator_repeat_with", issue = "48169")] +impl<A, F: FnMut() -> A> Iterator for RepeatWith<F> { + type Item = A; + + #[inline] + fn next(&mut self) -> Option<A> { Some((self.repeater)()) } + + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { (usize::MAX, None) } +} + +#[unstable(feature = "iterator_repeat_with", issue = "48169")] +impl<A, F: FnMut() -> A> DoubleEndedIterator for RepeatWith<F> { + #[inline] + fn next_back(&mut self) -> Option<A> { self.next() } +} + +#[unstable(feature = "fused", issue = "35602")] +impl<A, F: FnMut() -> A> FusedIterator for RepeatWith<F> {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl<A, F: FnMut() -> A> TrustedLen for RepeatWith<F> {} + +/// Creates a new iterator that repeats elements of type `A` endlessly by +/// applying the provided closure, the repeater, `F: FnMut() -> A`. +/// +/// The `repeat_with()` function calls the repeater over and over and over and +/// over and over and 🔁. +/// +/// Infinite iterators like `repeat_with()` are often used with adapters like +/// [`take`], in order to make them finite. +/// +/// [`take`]: trait.Iterator.html#method.take +/// +/// If the element type of the iterator you need implements `Clone`, and +/// it is OK to keep the source element in memory, you should instead use +/// the [`repeat`] function. +/// +/// [`repeat`]: fn.repeat.html +/// +/// An iterator produced by `repeat_with()` is a `DoubleEndedIterator`. +/// It is important to not that reversing `repeat_with(f)` will produce +/// the exact same sequence as the non-reversed iterator. In other words, +/// `repeat_with(f).rev().collect::<Vec<_>>()` is equivalent to +/// `repeat_with(f).collect::<Vec<_>>()`. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// #![feature(iterator_repeat_with)] +/// +/// use std::iter; +/// +/// // let's assume we have some value of a type that is not `Clone` +/// // or which don't want to have in memory just yet because it is expensive: +/// #[derive(PartialEq, Debug)] +/// struct Expensive; +/// +/// // a particular value forever: +/// let mut things = iter::repeat_with(|| Expensive); +/// +/// assert_eq!(Some(Expensive), things.next()); +/// assert_eq!(Some(Expensive), things.next()); +/// assert_eq!(Some(Expensive), things.next()); +/// assert_eq!(Some(Expensive), things.next()); +/// assert_eq!(Some(Expensive), things.next()); +/// ``` +/// +/// Using mutation and going finite: +/// +/// ```rust +/// #![feature(iterator_repeat_with)] +/// +/// use std::iter; +/// +/// // From the zeroth to the third power of two: +/// let mut curr = 1; +/// let mut pow2 = iter::repeat_with(|| { let tmp = curr; curr *= 2; tmp }) +/// .take(4); +/// +/// assert_eq!(Some(1), pow2.next()); +/// assert_eq!(Some(2), pow2.next()); +/// assert_eq!(Some(4), pow2.next()); +/// assert_eq!(Some(8), pow2.next()); +/// +/// // ... and now we're done +/// assert_eq!(None, pow2.next()); +/// ``` +#[inline] +#[unstable(feature = "iterator_repeat_with", issue = "48169")] +pub fn repeat_with<A, F: FnMut() -> A>(repeater: F) -> RepeatWith<F> { + RepeatWith { repeater } +} + /// An iterator that yields nothing. /// /// This `struct` is created by the [`empty`] function. See its documentation for more. |
