Skip to content
Browse files

clojure.core.reduce copied over from Clojure

Copy and paste with protocol & protocol method names adjusted,
Exception changed to Error and (set! *warn-on-reflection* true)
removed.
  • Loading branch information...
1 parent a8ac1f4 commit 73a568457bb95cc98c8eb62faf5e755680ba55e1 @michalmarczyk michalmarczyk committed with David Nolen May 2, 2012
Showing with 121 additions and 0 deletions.
  1. +121 −0 src/cljs/clojure/core/reduce.cljs
View
121 src/cljs/clojure/core/reduce.cljs
@@ -0,0 +1,121 @@
+; Copyright (c) Rich Hickey. All rights reserved.
+; The use and distribution terms for this software are covered by the
+; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+; which can be found in the file epl-v10.html at the root of this distribution.
+; By using this software in any fashion, you are agreeing to be bound by
+; the terms of this license.
+; You must not remove this notice, or any other, from this software.
+
+(ns clojure.core.reduce
+ (:refer-clojure :exclude [map filter remove take take-while drop flatten]))
+
+(defn reducer
+ "Given a reducible collection, and a transformation function xf,
+ returns a reducible collection, where any supplied reducing
+ fn will be transformed by xf. xf is a function of reducing fn to
+ reducing fn."
+ [coll xf]
+ (reify cljs.core/IReduce
+ (-reduce [_ f1]
+ (throw (js/Error. "You must supply an init value for reducer-based reduce")))
+ (-reduce [_ f1 init]
+ (-reduce coll (xf f1) init))))
+
+(defn map
+ "Applies f to every value in the reduction of coll"
+ [f coll]
+ (reducer
+ coll
+ (fn [f1]
+ (fn [ret v] (f1 ret (f v))))))
+
+(defn filter
+ "Retains values in the reduction of coll for which (pred val) returns logical true"
+ [pred coll]
+ (reducer
+ coll
+ (fn [f1]
+ (fn [ret v]
+ (if (pred v)
+ (f1 ret v)
+ ret)))))
+
+(defn remove
+ "Removes values in the reduction of coll for which (pred val) returns logical true"
+ [pred coll]
+ (filter (complement pred) coll))
+
+(defn take-while
+ "Ends the reduction of coll when (pred val) returns logical false."
+ [pred coll]
+ (reducer
+ coll
+ (fn [f1]
+ (fn [ret v]
+ (if (pred v)
+ (f1 ret v)
+ (reduced ret))))))
+
+(defn take
+ "Ends the reduction of coll after consuming n values."
+ [n coll]
+ (reducer
+ coll
+ (fn [f1]
+ (let [cnt (atom n)]
+ (fn [ret v]
+ (swap! cnt dec)
+ (if (neg? @cnt)
+ (reduced ret)
+ (f1 ret v)))))))
+
+(defn drop
+ "Elides the first n values from the reduction of coll."
+ [n coll]
+ (reducer
+ coll
+ (fn [f1]
+ (let [cnt (atom n)]
+ (fn [ret v]
+ (swap! cnt dec)
+ (if (neg? @cnt)
+ (f1 ret v)
+ ret))))))
+
+(defn flatten
+ "Takes any nested combination of sequential things (lists, vectors,
+ etc.) and returns their contents as a single, flat reducible
+ collection."
+ [coll]
+ (reify cljs.core/IReduce
+ (-reduce [_ f1]
+ (throw (js/Error. "You must supply an init value for reducer-based reduce")))
+ (-reduce [_ f1 init]
+ (-reduce
+ coll
+ (fn [ret v]
+ (if (sequential? v)
+ (-reduce (flatten v) f1 ret)
+ (f1 ret v)))
+ init))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(comment
+(require '[clojure.core.reduce :as r])
+(def v (take 1000000 (range)))
+(reduce + 0 (r/map inc [1 2 3 4]))
+(into [] (r/take 12 (range 100)))
+(into [] (r/drop 12 (range 100)))
+(reduce + 0 (r/filter even? [1 2 3 4]))
+(into [] (r/filter even? [1 2 3 4]))
+(reduce + (filter even? [1 2 3 4]))
+(dotimes [_ 10] (time (reduce + 0 (r/map inc v))))
+(dotimes [_ 10] (time (reduce + 0 (map inc v))))
+(dotimes [_ 100] (time (reduce + 0 v)))
+(dotimes [_ 100] (time (reduce + 0 v)))
+(dotimes [_ 20] (time (reduce + 0 (r/map inc (r/filter even? v)))))
+(dotimes [_ 20] (time (reduce + 0 (map inc (filter even? v)))))
+(reduce + 0 (r/take-while even? [2 4 3]))
+(into [] (r/filter even? (r/flatten (r/remove #{4} [[1 2 3] 4 [5 [6 7 8]] [9] 10]))))
+(into [] (r/flatten nil))
+)

0 comments on commit 73a5684

Please sign in to comment.
Something went wrong with that request. Please try again.