diff options
author | Konrad Hinsen <konrad.hinsen@laposte.net> | 2009-02-12 15:52:04 +0000 |
---|---|---|
committer | Konrad Hinsen <konrad.hinsen@laposte.net> | 2009-02-12 15:52:04 +0000 |
commit | fdb01a991717cdddfa3feca44ef71fdf0b7fb7d7 (patch) | |
tree | c1fbc4ef1c7b11bc50bcac0640b45fb8e4fdb656 /src | |
parent | 5550ed9a2215a927c3681b91113bc1d0fd36c04d (diff) |
accumulators: new minimum and maximum accumulators
Diffstat (limited to 'src')
-rw-r--r-- | src/clojure/contrib/accumulators.clj | 83 |
1 files changed, 39 insertions, 44 deletions
diff --git a/src/clojure/contrib/accumulators.clj b/src/clojure/contrib/accumulators.clj index 93a13037..9fe140a7 100644 --- a/src/clojure/contrib/accumulators.clj +++ b/src/clojure/contrib/accumulators.clj @@ -1,7 +1,7 @@ ;; Accumulators ;; by Konrad Hinsen -;; last updated February 3, 2009 +;; last updated February 12, 2009 ;; This module defines various accumulators (list, vector, map, ;; sum, product, counter, and combinations thereof) with a common @@ -20,7 +20,7 @@ (ns clojure.contrib.accumulators (:use [clojure.contrib.macros :only (letfn)]) - (:use [clojure.contrib.def :only (defvar defvar- defstruct-)])) + (:use [clojure.contrib.def :only (defvar defvar- defmacro-)])) (defn- selector [& vs] @@ -137,51 +137,46 @@ (conj v e)) ; -; Sum accumulator -; -(defstruct- sum :sum) - -(defvar- get-sum (accessor sum :sum)) - -(let [sum-tag {::accumulator ::sum}] - (defn- make-sum - [n] - (with-meta (struct sum 0) sum-tag))) - -(defvar empty-sum (make-sum 0) +; Numerical accumulators: sum, product, minimum, maximum +; +(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#)))))) + +(defacc sum + 0 "An empty sum accumulator. Only numbers can be added.") -(defmethod combine ::sum - [& vs] - (make-sum (apply + (map get-sum vs)))) - -(defmethod add ::sum - [v e] - (make-sum (+ (get-sum v) e))) - -; -; Product accumulator -; -(defstruct- product :product) - -(defvar- get-product (accessor product :product)) - -(let [product-tag {::accumulator ::product}] - (defn- make-product - [n] - (with-meta (struct product n) product-tag))) - -(defvar empty-product (make-product 1) - "An empty product accumulator. Only numbers can be added. Note that - addition means multiplication in this case!") - -(defmethod combine ::product - [& vs] - (make-product (apply * (map get-product vs)))) +(defacc product * 1 + "An empty sum accumulator. Only numbers can be added.") -(defmethod add ::product - [v e] - (make-product (* (get-product v) e))) +; The empty maximum accumulator should have value -infinity. +; This is represented by nil and taken into account in an +; adapted max function. In the minimum accumulator, nil is +; similarly used to represent +infinity. + +(defacc maximum (fn [& xs] + (when-let [xs (filter identity xs)] + (apply max xs))) + nil + "An empty maximum accumulator. Only numbers can be added.") + +(defacc minimum (fn [& xs] + (when-let [xs (filter identity xs)] + (apply min xs))) + nil + "An empty minimum accumulator. Only numbers can be added.") ; ; Counter accumulator |