Skip to content

Commit 0f789aa

Browse files
committed
add core::iter::repeat_with
1 parent b8398d9 commit 0f789aa

File tree

2 files changed

+148
-0
lines changed

2 files changed

+148
-0
lines changed

src/libcore/iter/sources.rs

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

src/libcore/tests/iter.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1549,6 +1549,50 @@ fn test_repeat_take_collect() {
15491549
assert_eq!(v, vec![42, 42, 42]);
15501550
}
15511551

1552+
#[test]
1553+
fn test_repeat_with() {
1554+
struct NotClone(usize);
1555+
let mut it = repeat_with(|| NotClone(42));
1556+
assert_eq!(it.next(), Some(NotClone(42)));
1557+
assert_eq!(it.next(), Some(NotClone(42)));
1558+
assert_eq!(it.next(), Some(NotClone(42)));
1559+
assert_eq!(repeat_with(|| NotClone(42)).size_hint(), (usize::MAX, None));
1560+
}
1561+
1562+
#[test]
1563+
fn test_repeat_with_rev() {
1564+
let mut curr = 1;
1565+
let mut pow2 = repeat_with(|| { let tmp = curr; curr *= 2; tmp })
1566+
.rev().take(4);
1567+
assert_eq!(it.next(), Some(1));
1568+
assert_eq!(it.next(), Some(2));
1569+
assert_eq!(it.next(), Some(4));
1570+
assert_eq!(it.next(), Some(8));
1571+
assert_eq!(it.next(), None);
1572+
}
1573+
1574+
#[test]
1575+
fn test_repeat_with_take() {
1576+
let mut it = repeat_with(|| 42).take(3);
1577+
assert_eq!(it.next(), Some(42));
1578+
assert_eq!(it.next(), Some(42));
1579+
assert_eq!(it.next(), Some(42));
1580+
assert_eq!(it.next(), None);
1581+
is_trusted_len(repeat_with(|| 42).take(3));
1582+
assert_eq!(repeat_with(|| 42).take(3).size_hint(), (3, Some(3)));
1583+
assert_eq!(repeat_with(|| 42).take(0).size_hint(), (0, Some(0)));
1584+
assert_eq!(repeat_with(|| 42).take(usize::MAX).size_hint(),
1585+
(usize::MAX, Some(usize::MAX)));
1586+
}
1587+
1588+
#[test]
1589+
fn test_repeat_take_collect() {
1590+
let mut curr = 1;
1591+
let v: Vec<_> = repeat_with(|| { let tmp = curr; curr *= 2; tmp })
1592+
.take(5).collect();
1593+
assert_eq!(v, vec![1, 2, 4, 8, 16]);
1594+
}
1595+
15521596
#[test]
15531597
fn test_fuse() {
15541598
let mut it = 0..3;

0 commit comments

Comments
 (0)