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
This commit is contained in:
commit
bebd2fbfc8
5 changed files with 164 additions and 0 deletions
|
@ -333,6 +333,8 @@ pub use self::range::Step;
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub use self::sources::{Repeat, repeat};
|
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")]
|
#[stable(feature = "iter_empty", since = "1.2.0")]
|
||||||
pub use self::sources::{Empty, empty};
|
pub use self::sources::{Empty, empty};
|
||||||
#[stable(feature = "iter_once", since = "1.2.0")]
|
#[stable(feature = "iter_once", since = "1.2.0")]
|
||||||
|
|
|
@ -57,6 +57,12 @@ unsafe impl<A: Clone> TrustedLen for Repeat<A> {}
|
||||||
///
|
///
|
||||||
/// [`take`]: trait.Iterator.html#method.take
|
/// [`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
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// Basic usage:
|
/// Basic usage:
|
||||||
|
@ -99,6 +105,115 @@ pub fn repeat<T: Clone>(elt: T) -> Repeat<T> {
|
||||||
Repeat{element: elt}
|
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.
|
/// An iterator that yields nothing.
|
||||||
///
|
///
|
||||||
/// This `struct` is created by the [`empty`] function. See its documentation for more.
|
/// This `struct` is created by the [`empty`] function. See its documentation for more.
|
||||||
|
|
|
@ -92,6 +92,7 @@
|
||||||
#![feature(unwind_attributes)]
|
#![feature(unwind_attributes)]
|
||||||
#![feature(doc_spotlight)]
|
#![feature(doc_spotlight)]
|
||||||
#![feature(rustc_const_unstable)]
|
#![feature(rustc_const_unstable)]
|
||||||
|
#![feature(iterator_repeat_with)]
|
||||||
|
|
||||||
#[prelude_import]
|
#[prelude_import]
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
|
|
@ -1592,6 +1592,51 @@ fn test_repeat_take_collect() {
|
||||||
assert_eq!(v, vec![42, 42, 42]);
|
assert_eq!(v, vec![42, 42, 42]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_repeat_with() {
|
||||||
|
#[derive(PartialEq, Debug)]
|
||||||
|
struct NotClone(usize);
|
||||||
|
let mut it = repeat_with(|| NotClone(42));
|
||||||
|
assert_eq!(it.next(), Some(NotClone(42)));
|
||||||
|
assert_eq!(it.next(), Some(NotClone(42)));
|
||||||
|
assert_eq!(it.next(), Some(NotClone(42)));
|
||||||
|
assert_eq!(repeat_with(|| NotClone(42)).size_hint(), (usize::MAX, None));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_repeat_with_rev() {
|
||||||
|
let mut curr = 1;
|
||||||
|
let mut pow2 = repeat_with(|| { let tmp = curr; curr *= 2; tmp })
|
||||||
|
.rev().take(4);
|
||||||
|
assert_eq!(pow2.next(), Some(1));
|
||||||
|
assert_eq!(pow2.next(), Some(2));
|
||||||
|
assert_eq!(pow2.next(), Some(4));
|
||||||
|
assert_eq!(pow2.next(), Some(8));
|
||||||
|
assert_eq!(pow2.next(), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_repeat_with_take() {
|
||||||
|
let mut it = repeat_with(|| 42).take(3);
|
||||||
|
assert_eq!(it.next(), Some(42));
|
||||||
|
assert_eq!(it.next(), Some(42));
|
||||||
|
assert_eq!(it.next(), Some(42));
|
||||||
|
assert_eq!(it.next(), None);
|
||||||
|
is_trusted_len(repeat_with(|| 42).take(3));
|
||||||
|
assert_eq!(repeat_with(|| 42).take(3).size_hint(), (3, Some(3)));
|
||||||
|
assert_eq!(repeat_with(|| 42).take(0).size_hint(), (0, Some(0)));
|
||||||
|
assert_eq!(repeat_with(|| 42).take(usize::MAX).size_hint(),
|
||||||
|
(usize::MAX, Some(usize::MAX)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_repeat_with_take_collect() {
|
||||||
|
let mut curr = 1;
|
||||||
|
let v: Vec<_> = repeat_with(|| { let tmp = curr; curr *= 2; tmp })
|
||||||
|
.take(5).collect();
|
||||||
|
assert_eq!(v, vec![1, 2, 4, 8, 16]);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fuse() {
|
fn test_fuse() {
|
||||||
let mut it = 0..3;
|
let mut it = 0..3;
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#![feature(iterator_try_fold)]
|
#![feature(iterator_try_fold)]
|
||||||
#![feature(iter_rfind)]
|
#![feature(iter_rfind)]
|
||||||
#![feature(iter_rfold)]
|
#![feature(iter_rfold)]
|
||||||
|
#![feature(iterator_repeat_with)]
|
||||||
#![feature(nonzero)]
|
#![feature(nonzero)]
|
||||||
#![feature(pattern)]
|
#![feature(pattern)]
|
||||||
#![feature(range_is_empty)]
|
#![feature(range_is_empty)]
|
||||||
|
|
Loading…
Reference in a new issue