From 12a52a05599316ccca42451d28b9ec9564915737 Mon Sep 17 00:00:00 2001
From: Alan Malloy <alan@malloys.org>
Date: Sat, 18 Aug 2012 16:39:20 -0700
Subject: [PATCH 3/4] Implement iterate as a reducer.

---
 src/clj/clojure/core/reducers.clj      |   20 +++++++++++++++++++-
 test/clojure/test_clojure/reducers.clj |    7 +++++++
 2 files changed, 26 insertions(+), 1 deletions(-)

diff --git a/src/clj/clojure/core/reducers.clj b/src/clj/clojure/core/reducers.clj
index 3a71f7f..5ea580c 100644
--- a/src/clj/clojure/core/reducers.clj
+++ b/src/clj/clojure/core/reducers.clj
@@ -13,7 +13,7 @@
       dependency info."
       :author "Rich Hickey"}
   clojure.core.reducers
-  (:refer-clojure :exclude [reduce map mapcat filter remove take take-while drop drop-while flatten])
+  (:refer-clojure :exclude [reduce map mapcat filter remove take take-while drop drop-while flatten iterate])
   (:require [clojure.walk :as walk]))
 
 (alias 'core 'clojure.core)
@@ -335,6 +335,24 @@
       :else
       (Cat. (+ (count left) (count right)) left right))))
 
+(defcurried iterate
+  "A reducible collection of [seed, (f seed), (f (f seed)), ...]"
+  {:added "1.5"}
+  [f seed]
+  (reify
+    clojure.core.protocols/CollReduce
+    (coll-reduce [this f1] (clojure.core.protocols/coll-reduce this f1 (f1)))
+    (coll-reduce [this f1 init]
+      (loop [ret (f1 init seed), seed seed]
+        (if (reduced? ret)
+          @ret
+          (let [next (f seed)]
+            (recur (f1 ret next) next)))))
+
+    clojure.lang.Seqable
+    (seq [this]
+      (seq (clojure.core/iterate f seed)))))
+
 (defn append!
   ".adds x to acc and returns acc"
   {:added "1.5"}
diff --git a/test/clojure/test_clojure/reducers.clj b/test/clojure/test_clojure/reducers.clj
index fdc4895..2092806 100644
--- a/test/clojure/test_clojure/reducers.clj
+++ b/test/clojure/test_clojure/reducers.clj
@@ -44,6 +44,13 @@
   [drop-while r/drop-while #(into [] %)]
   [neg? pos? #(< % 200) #(> % 200) #{-100}])
 
+(deftest test-iterate
+  (is (= [100000]
+         (->> (r/iterate inc 0)
+              (r/drop 1e5)
+              (r/take 1)
+              (into [])))))
+
 
 (deftest test-sorted-maps
   (let [m (into (sorted-map)
-- 
1.7.0.4

