Skip to content

Commit bebd2fb

Browse files
committed
Rollup merge of rust-lang#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
2 parents dcb1526 + db13296 commit bebd2fb

File tree

5 files changed

+164
-0
lines changed

5 files changed

+164
-0
lines changed

src/libcore/iter/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,8 @@ pub use self::range::Step;
333333

334334
#[stable(feature = "rust1", since = "1.0.0")]
335335
pub use self::sources::{Repeat, repeat};
336+
#[unstable(feature = "iterator_repeat_with", issue = "48169")]
337+
pub use self::sources::{RepeatWith, repeat_with};
336338
#[stable(feature = "iter_empty", since = "1.2.0")]
337339
pub use self::sources::{Empty, empty};
338340
#[stable(feature = "iter_once", since = "1.2.0")]

src/libcore/iter/sources.rs

+115
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ unsafe impl<A: Clone> TrustedLen for Repeat<A> {}
5757
///
5858
/// [`take`]: trait.Iterator.html#method.take
5959
///
60+
/// If the element type of the iterator you need does not implement `Clone`,
61+
/// or if you do not want to keep the repeated element in memory, you can
62+
/// instead use the [`repeat_with`] function.
63+
///
64+
/// [`repeat_with`]: fn.repeat_with.html
65+
///
6066
/// # Examples
6167
///
6268
/// Basic usage:
@@ -99,6 +105,115 @@ pub fn repeat<T: Clone>(elt: T) -> Repeat<T> {
99105
Repeat{element: elt}
100106
}
101107

108+
/// An iterator that repeats elements of type `A` endlessly by
109+
/// applying the provided closure `F: FnMut() -> A`.
110+
///
111+
/// This `struct` is created by the [`repeat_with`] function.
112+
/// See its documentation for more.
113+
///
114+
/// [`repeat_with`]: fn.repeat_with.html
115+
#[derive(Copy, Clone, Debug)]
116+
#[unstable(feature = "iterator_repeat_with", issue = "48169")]
117+
pub struct RepeatWith<F> {
118+
repeater: F
119+
}
120+
121+
#[unstable(feature = "iterator_repeat_with", issue = "48169")]
122+
impl<A, F: FnMut() -> A> Iterator for RepeatWith<F> {
123+
type Item = A;
124+
125+
#[inline]
126+
fn next(&mut self) -> Option<A> { Some((self.repeater)()) }
127+
128+
#[inline]
129+
fn size_hint(&self) -> (usize, Option<usize>) { (usize::MAX, None) }
130+
}
131+
132+
#[unstable(feature = "iterator_repeat_with", issue = "48169")]
133+
impl<A, F: FnMut() -> A> DoubleEndedIterator for RepeatWith<F> {
134+
#[inline]
135+
fn next_back(&mut self) -> Option<A> { self.next() }
136+
}
137+
138+
#[unstable(feature = "fused", issue = "35602")]
139+
impl<A, F: FnMut() -> A> FusedIterator for RepeatWith<F> {}
140+
141+
#[unstable(feature = "trusted_len", issue = "37572")]
142+
unsafe impl<A, F: FnMut() -> A> TrustedLen for RepeatWith<F> {}
143+
144+
/// Creates a new iterator that repeats elements of type `A` endlessly by
145+
/// applying the provided closure, the repeater, `F: FnMut() -> A`.
146+
///
147+
/// The `repeat_with()` function calls the repeater over and over and over and
148+
/// over and over and 🔁.
149+
///
150+
/// Infinite iterators like `repeat_with()` are often used with adapters like
151+
/// [`take`], in order to make them finite.
152+
///
153+
/// [`take`]: trait.Iterator.html#method.take
154+
///
155+
/// If the element type of the iterator you need implements `Clone`, and
156+
/// it is OK to keep the source element in memory, you should instead use
157+
/// the [`repeat`] function.
158+
///
159+
/// [`repeat`]: fn.repeat.html
160+
///
161+
/// An iterator produced by `repeat_with()` is a `DoubleEndedIterator`.
162+
/// It is important to not that reversing `repeat_with(f)` will produce
163+
/// the exact same sequence as the non-reversed iterator. In other words,
164+
/// `repeat_with(f).rev().collect::<Vec<_>>()` is equivalent to
165+
/// `repeat_with(f).collect::<Vec<_>>()`.
166+
///
167+
/// # Examples
168+
///
169+
/// Basic usage:
170+
///
171+
/// ```
172+
/// #![feature(iterator_repeat_with)]
173+
///
174+
/// use std::iter;
175+
///
176+
/// // let's assume we have some value of a type that is not `Clone`
177+
/// // or which don't want to have in memory just yet because it is expensive:
178+
/// #[derive(PartialEq, Debug)]
179+
/// struct Expensive;
180+
///
181+
/// // a particular value forever:
182+
/// let mut things = iter::repeat_with(|| Expensive);
183+
///
184+
/// assert_eq!(Some(Expensive), things.next());
185+
/// assert_eq!(Some(Expensive), things.next());
186+
/// assert_eq!(Some(Expensive), things.next());
187+
/// assert_eq!(Some(Expensive), things.next());
188+
/// assert_eq!(Some(Expensive), things.next());
189+
/// ```
190+
///
191+
/// Using mutation and going finite:
192+
///
193+
/// ```rust
194+
/// #![feature(iterator_repeat_with)]
195+
///
196+
/// use std::iter;
197+
///
198+
/// // From the zeroth to the third power of two:
199+
/// let mut curr = 1;
200+
/// let mut pow2 = iter::repeat_with(|| { let tmp = curr; curr *= 2; tmp })
201+
/// .take(4);
202+
///
203+
/// assert_eq!(Some(1), pow2.next());
204+
/// assert_eq!(Some(2), pow2.next());
205+
/// assert_eq!(Some(4), pow2.next());
206+
/// assert_eq!(Some(8), pow2.next());
207+
///
208+
/// // ... and now we're done
209+
/// assert_eq!(None, pow2.next());
210+
/// ```
211+
#[inline]
212+
#[unstable(feature = "iterator_repeat_with", issue = "48169")]
213+
pub fn repeat_with<A, F: FnMut() -> A>(repeater: F) -> RepeatWith<F> {
214+
RepeatWith { repeater }
215+
}
216+
102217
/// An iterator that yields nothing.
103218
///
104219
/// This `struct` is created by the [`empty`] function. See its documentation for more.

src/libcore/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
#![feature(unwind_attributes)]
9393
#![feature(doc_spotlight)]
9494
#![feature(rustc_const_unstable)]
95+
#![feature(iterator_repeat_with)]
9596

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

src/libcore/tests/iter.rs

+45
Original file line numberDiff line numberDiff line change
@@ -1592,6 +1592,51 @@ fn test_repeat_take_collect() {
15921592
assert_eq!(v, vec![42, 42, 42]);
15931593
}
15941594

1595+
#[test]
1596+
fn test_repeat_with() {
1597+
#[derive(PartialEq, Debug)]
1598+
struct NotClone(usize);
1599+
let mut it = repeat_with(|| NotClone(42));
1600+
assert_eq!(it.next(), Some(NotClone(42)));
1601+
assert_eq!(it.next(), Some(NotClone(42)));
1602+
assert_eq!(it.next(), Some(NotClone(42)));
1603+
assert_eq!(repeat_with(|| NotClone(42)).size_hint(), (usize::MAX, None));
1604+
}
1605+
1606+
#[test]
1607+
fn test_repeat_with_rev() {
1608+
let mut curr = 1;
1609+
let mut pow2 = repeat_with(|| { let tmp = curr; curr *= 2; tmp })
1610+
.rev().take(4);
1611+
assert_eq!(pow2.next(), Some(1));
1612+
assert_eq!(pow2.next(), Some(2));
1613+
assert_eq!(pow2.next(), Some(4));
1614+
assert_eq!(pow2.next(), Some(8));
1615+
assert_eq!(pow2.next(), None);
1616+
}
1617+
1618+
#[test]
1619+
fn test_repeat_with_take() {
1620+
let mut it = repeat_with(|| 42).take(3);
1621+
assert_eq!(it.next(), Some(42));
1622+
assert_eq!(it.next(), Some(42));
1623+
assert_eq!(it.next(), Some(42));
1624+
assert_eq!(it.next(), None);
1625+
is_trusted_len(repeat_with(|| 42).take(3));
1626+
assert_eq!(repeat_with(|| 42).take(3).size_hint(), (3, Some(3)));
1627+
assert_eq!(repeat_with(|| 42).take(0).size_hint(), (0, Some(0)));
1628+
assert_eq!(repeat_with(|| 42).take(usize::MAX).size_hint(),
1629+
(usize::MAX, Some(usize::MAX)));
1630+
}
1631+
1632+
#[test]
1633+
fn test_repeat_with_take_collect() {
1634+
let mut curr = 1;
1635+
let v: Vec<_> = repeat_with(|| { let tmp = curr; curr *= 2; tmp })
1636+
.take(5).collect();
1637+
assert_eq!(v, vec![1, 2, 4, 8, 16]);
1638+
}
1639+
15951640
#[test]
15961641
fn test_fuse() {
15971642
let mut it = 0..3;

src/libcore/tests/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#![feature(iterator_try_fold)]
2828
#![feature(iter_rfind)]
2929
#![feature(iter_rfold)]
30+
#![feature(iterator_repeat_with)]
3031
#![feature(nonzero)]
3132
#![feature(pattern)]
3233
#![feature(range_is_empty)]

0 commit comments

Comments
 (0)