aboutsummaryrefslogtreecommitdiff
path: root/src/clojure/contrib/accumulators.clj
diff options
context:
space:
mode:
Diffstat (limited to 'src/clojure/contrib/accumulators.clj')
-rw-r--r--src/clojure/contrib/accumulators.clj139
1 files changed, 60 insertions, 79 deletions
diff --git a/src/clojure/contrib/accumulators.clj b/src/clojure/contrib/accumulators.clj
index f06badf7..d32dbda6 100644
--- a/src/clojure/contrib/accumulators.clj
+++ b/src/clojure/contrib/accumulators.clj
@@ -1,7 +1,7 @@
;; Accumulators
;; by Konrad Hinsen
-;; last updated March 2, 2009
+;; last updated March 11, 2009
;; This module defines various accumulators (list, vector, map,
;; sum, product, counter, and combinations thereof) with a common
@@ -19,7 +19,7 @@
;; remove this notice, or any other, from this software.
(ns clojure.contrib.accumulators
- (:use [clojure.contrib.types :only (deftype get-value get-values)])
+ (:use [clojure.contrib.types :only (deftype)])
(:use [clojure.contrib.def :only (defvar defvar- defmacro-)]))
(defmulti add
@@ -135,31 +135,17 @@
;
(defmacro- defacc
[name op empty doc-string]
- (let [type-name (symbol (str name "-type"))
+ (let [type-tag (keyword (str *ns*) (str name))
empty-symbol (symbol (str "empty-" name))]
`(let [op# ~op]
- (deftype ~type-name (~name ~'v))
+ (deftype ~type-tag ~name
+ (fn [~'x] {:value ~'x})
+ (fn [~'x] (list (:value ~'x))))
(defvar ~empty-symbol (~name ~empty) ~doc-string)
- (defmethod combine ~type-name [& vs#]
- (~name (apply op# (map clojure.contrib.types/get-value vs#))))
- (defmethod add ~type-name [v# e#]
- (~name (op# (clojure.contrib.types/get-value v#) e#))))))
-
-;; (defmacro- defacc
-;; [name op empty doc-string]
-;; (let [struct-tag (keyword (str name))
-;; meta-tag (keyword (str *ns*) (str name))
-;; empty-symbol (symbol (str "empty-" name))]
-;; `(let [op# ~op
-;; meta-data# {::accumulator ~meta-tag}
-;; struct-basis# (create-struct ~struct-tag)
-;; get-value# (accessor struct-basis# ~struct-tag)
-;; make-fn# (fn [n#] (with-meta (struct struct-basis# n#) meta-data#))]
-;; (defvar ~empty-symbol (make-fn# ~empty) ~doc-string)
-;; (defmethod combine ~meta-tag [& vs#]
-;; (make-fn# (apply op# (map get-value# vs#))))
-;; (defmethod add ~meta-tag [v# e#]
-;; (make-fn# (op# (get-value# v#) e#))))))
+ (defmethod combine ~type-tag [& vs#]
+ (~name (apply op# (map :value vs#))))
+ (defmethod add ~type-tag [v# e#]
+ (~name (op# (:value v#) e#))))))
(defacc sum + 0
"An empty sum accumulator. Only numbers can be added.")
@@ -188,23 +174,24 @@
; Numeric min-max accumulator
; (combination of minimum and maximum)
;
-(deftype min-max-type
- (min-max min max))
+(deftype ::min-max min-max
+ (fn [min max] {:min min :max max})
+ (fn [mm] (list (:min mm) (:max mm))))
(defvar empty-min-max (min-max nil nil)
"An empty min-max accumulator, combining minimum and maximum.
Only numbers can be added.")
-(defmethod combine min-max-type
+(defmethod combine ::min-max
[& vs]
- (let [values (map get-values vs)
- total-min (apply min (map first values))
- total-max (apply max (map second values))]
+ (let [total-min (apply min (map :min vs))
+ total-max (apply max (map :max vs))]
(min-max total-min total-max)))
-(defmethod add min-max-type
+(defmethod add ::min-max
[v e]
- (let [[min-v max-v] (get-values v)
+ (let [min-v (:min v)
+ max-v (:max v)
new-min (if (nil? min-v) e (min min-v e))
new-max (if (nil? max-v) e (max max-v e))]
(min-max new-min new-max)))
@@ -212,63 +199,57 @@
;
; Counter accumulator
;
-(let [type-tag ::counter
- meta-map {:type type-tag}]
+(deftype ::counter counter)
- (defvar empty-counter (with-meta {} meta-map)
- "An empty counter accumulator. Its value is a map that stores for
- every item the number of times it was added.")
+(defvar empty-counter (counter {})
+ "An empty counter accumulator. Its value is a map that stores for
+ every item the number of times it was added.")
- (defmethod combine type-tag
- [v & vs]
- (letfn [(add-item [counter [item n]]
- (assoc counter item (+ n (get counter item 0))))
- (add-two [c1 c2] (reduce add-item c1 c2))]
- (reduce add-two v vs)))
+(defmethod combine ::counter
+ [v & vs]
+ (letfn [(add-item [cntr [item n]]
+ (assoc cntr item (+ n (get cntr item 0))))
+ (add-two [c1 c2] (reduce add-item c1 c2))]
+ (reduce add-two v vs)))
- (defmethod add type-tag
- [v e]
- (assoc v e (inc (get v e 0)))))
+(defmethod add ::counter
+ [v e]
+ (assoc v e (inc (get v e 0))))
;
; Counter accumulator with total count
;
+(deftype ::counter-with-total counter-with-total)
+(derive ::counter-with-total ::counter)
-(let [type-tag ::counter-with-total
- meta-map {:type type-tag}]
-
- (derive type-tag ::counter)
-
- (defvar empty-counter-with-total
- (with-meta {:total 0} meta-map)
- "An empty counter-with-total accumulator. It works like the counter
- accumulator, except that the total number of items added is stored as the
- value of the key :totall.")
+(defvar empty-counter-with-total
+ (counter-with-total {:total 0})
+ "An empty counter-with-total accumulator. It works like the counter
+ accumulator, except that the total number of items added is stored as the
+ value of the key :total.")
- (defmethod add type-tag
- [v e]
- (assoc v e (inc (get v e 0))
- :total (inc (:total v)))))
+(defmethod add ::counter-with-total
+ [v e]
+ (assoc v e (inc (get v e 0))
+ :total (inc (:total v))))
;
; Accumulator n-tuple
;
-(let [type-tag ::tuple
- meta-map {:type type-tag}
- make (fn [s] (with-meta (into [] s) meta-map))]
-
- (defn empty-tuple
- "Returns an accumulator tuple with the supplied empty-accumulators
- as its value. Accumulator tuples consist of several accumulators that
- work in parallel. Added items must be sequences whose number of elements
- matches the number of sub-accumulators."
- [empty-accumulators]
- (make empty-accumulators))
-
- (defmethod combine ::tuple
- [& vs]
- (make (map combine vs)))
-
- (defmethod add ::tuple
- [v e]
- (make (map add v e))))
+(deftype ::tuple acc-tuple)
+
+(defn empty-tuple
+ "Returns an accumulator tuple with the supplied empty-accumulators
+ as its value. Accumulator tuples consist of several accumulators that
+ work in parallel. Added items must be sequences whose number of elements
+ matches the number of sub-accumulators."
+ [empty-accumulators]
+ (acc-tuple (into [] empty-accumulators)))
+
+(defmethod combine ::tuple
+ [& vs]
+ (acc-tuple (vec (map combine vs))))
+
+(defmethod add ::tuple
+ [v e]
+ (acc-tuple (vec (map add v e))))