From ed54162e86cd00b7a4ced8957aac7f56897f6fb5 Mon Sep 17 00:00:00 2001 From: Jakub Wieczorek Date: Mon, 7 Jul 2014 00:50:53 +0200 Subject: [PATCH] Add an iterate function to core::iter Implementation by Kevin Ballard. The function returns an Unfold iterator producing an infinite stream of results of repeated applications of the function, starting from the provided seed value. --- src/libcore/iter.rs | 33 +++++++++++++++++++++++++++------ src/libcoretest/iter.rs | 9 +++++++++ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 80b784250f0..855bccb07a7 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -64,14 +64,14 @@ the rest of the rust manuals. */ -use cmp; -use num::{Zero, One, CheckedAdd, CheckedSub, Saturating, ToPrimitive, Int}; -use option::{Option, Some, None}; -use ops::{Add, Mul, Sub}; -use cmp::{PartialEq, PartialOrd, Ord}; use clone::Clone; -use uint; +use cmp; +use cmp::{PartialEq, PartialOrd, Ord}; use mem; +use num::{Zero, One, CheckedAdd, CheckedSub, Saturating, ToPrimitive, Int}; +use ops::{Add, Mul, Sub}; +use option::{Option, Some, None}; +use uint; /// Conversion from an `Iterator` pub trait FromIterator { @@ -2192,6 +2192,27 @@ impl RandomAccessIterator for Repeat { fn idx(&mut self, _: uint) -> Option { Some(self.element.clone()) } } +type IterateState<'a, T> = (|T|: 'a -> T, Option, bool); + +/// An iterator that repeatedly applies a given function, starting +/// from a given seed value. +pub type Iterate<'a, T> = Unfold<'a, T, IterateState<'a, T>>; + +/// Creates a new iterator that produces an infinite sequence of +/// repeated applications of the given function `f`. +#[allow(visible_private_types)] +pub fn iterate<'a, T: Clone>(f: |T|: 'a -> T, seed: T) -> Iterate<'a, T> { + Unfold::new((f, Some(seed), true), |st| { + let &(ref mut f, ref mut val, ref mut first) = st; + if *first { + *first = false; + } else { + val.mutate(|x| (*f)(x)); + } + val.clone() + }) +} + /// Functions for lexicographical ordering of sequences. /// /// Lexicographical ordering through `<`, `<=`, `>=`, `>` requires diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index 86b5ffece41..64c33609399 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -833,3 +833,12 @@ fn test_min_max_result() { let r = MinMax(1i,2); assert_eq!(r.into_option(), Some((1,2))); } + +#[test] +fn test_iterate() { + let mut it = iterate(|x| x * 2, 1u); + assert_eq!(it.next(), Some(1u)); + assert_eq!(it.next(), Some(2u)); + assert_eq!(it.next(), Some(4u)); + assert_eq!(it.next(), Some(8u)); +}