aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKonrad Hinsen <konrad.hinsen@laposte.net>2009-03-12 17:47:30 +0000
committerKonrad Hinsen <konrad.hinsen@laposte.net>2009-03-12 17:47:30 +0000
commit08cfc276dfc60d9a45b4dff7581597dd23682bfb (patch)
tree64d3823dbe05f0744e0ff025301cc4046362dc6b /src
parentea60eb05432f24f7244eb36a7f952236a04ebbb1 (diff)
New module clojure.contrib.generic.arithmetic (experimental)
Diffstat (limited to 'src')
-rw-r--r--src/clojure/contrib/gen_html_docs.clj1
-rw-r--r--src/clojure/contrib/generic/arithmetic.clj159
-rw-r--r--src/clojure/contrib/load_all.clj1
3 files changed, 161 insertions, 0 deletions
diff --git a/src/clojure/contrib/gen_html_docs.clj b/src/clojure/contrib/gen_html_docs.clj
index df9f9580..7cf62d9e 100644
--- a/src/clojure/contrib/gen_html_docs.clj
+++ b/src/clojure/contrib/gen_html_docs.clj
@@ -482,6 +482,7 @@ emits the generated HTML to the path named by path."
'clojure.contrib.error-kit
'clojure.contrib.except
'clojure.contrib.fcase
+ 'clojure.contrib.generic.arithmetic
'clojure.contrib.import-static
'clojure.contrib.javadoc
'clojure.contrib.javalog
diff --git a/src/clojure/contrib/generic/arithmetic.clj b/src/clojure/contrib/generic/arithmetic.clj
new file mode 100644
index 00000000..558ec37b
--- /dev/null
+++ b/src/clojure/contrib/generic/arithmetic.clj
@@ -0,0 +1,159 @@
+;; Generic interfaces for arithmetic operations
+
+;; by Konrad Hinsen
+;; last updated March 12, 2009
+
+;; Copyright (c) Konrad Hinsen, 2009. 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.contrib.generic.arithmetic
+ "Generic arithmetic interface
+
+ NOTE: This library is VERY experimental. It WILL change significantly
+ with future release.
+
+ This library defines generic versions of + - * / as multimethods
+ that can be defined for any type. The minimal required implementations
+ for a type are binary + and * plus unary - and /. Everything else
+ is derived from these automatically. Explicit binary definitions
+ for - and / can be given for efficiency reasons."
+ (:refer-clojure :exclude [+ - * /]))
+
+;
+; A dispatch function that separates nulary, unary, binary, and
+; higher arity calls and also selects on type for unary and binary
+; calls.
+;
+(defn- nary-dispatch
+ ([] ::nulary)
+ ([x] [::unary (type x)])
+ ([x y]
+ (let [tx (type x)
+ ty (type y)]
+ (cond (isa? tx ty) [::binary ty]
+ (isa? ty tx) [::binary tx]
+ ; Should there be clause checking if tx and ty have
+ ; a common ancestor? This would cover cases like
+ ; java.lang.Integer and java.lang.Double, which have the
+ ; common ancestor java.lang.Number.
+ :else [::binary tx ty])))
+ ([x y & more] ::n-ary))
+
+;
+; We can't use [::binary :default], so we need to define a root type
+; of the type hierarcy. The derivation for Object covers all classes,
+; but all non-class types will need an explicit derive clause.
+; Ultimately, a macro might take care of this.
+;
+(derive Object ::any)
+
+;
+; Addition
+;
+; The minimal implementation is for [::binary my-type]. It is possible
+; in principle to implement [::unary my-type] as well, though this
+; doesn't make any sense.
+;
+(defmulti + nary-dispatch)
+
+(defmethod + ::nulary
+ []
+ ::zero)
+
+(defmethod + [::unary ::any]
+ [x] x)
+
+(defmethod + ::n-ary
+ [x y & more]
+ (if more
+ (recur (+ x y) (first more) (next more))
+ (+ x y)))
+
+;
+; Subtraction
+;
+; The minimal implementation is for [::unary my-type]. A default binary
+; implementation is provided as (+ x (- y)), but it is possible to
+; implement [::unary my-type] explicitly for efficiency reasons.
+;
+(defmulti - nary-dispatch)
+
+(defmethod - ::nulary
+ []
+ (throw (java.lang.IllegalArgumentException.
+ "Wrong number of arguments passed")))
+
+(defmethod - [::binary ::any]
+ [x y] (+ x (- y)))
+
+(defmethod - ::n-ary
+ [x y & more]
+ (if more
+ (recur (- x y) (first more) (next more))
+ (- x y)))
+
+;
+; Multiplication
+;
+; The minimal implementation is for [::binary my-type]. It is possible
+; in principle to implement [::unary my-type] as well, though this
+; doesn't make any sense.
+;
+(defmulti * nary-dispatch)
+
+(defmethod * ::nulary
+ []
+ ::one)
+
+(defmethod * [::unary ::any]
+ [x] x)
+
+(defmethod * ::n-ary
+ [x y & more]
+ (if more
+ (recur (* x y) (first more) (next more))
+ (* x y)))
+
+;
+; Division
+;
+; The minimal implementation is for [::unary my-type]. A default binary
+; implementation is provided as (* x (/ y)), but it is possible to
+; implement [::unary my-type] explicitly for efficiency reasons.
+;
+(defmulti / nary-dispatch)
+
+(defmethod / ::nulary
+ []
+ (throw (java.lang.IllegalArgumentException.
+ "Wrong number of arguments passed")))
+
+(defmethod / [::binary ::any]
+ [x y] (* x (/ y)))
+
+(defmethod / ::n-ary
+ [x y & more]
+ (if more
+ (recur (/ x y) (first more) (next more))
+ (/ x y)))
+
+;
+; Minimal implementations for java.lang.Number
+;
+(defmethod + [::binary java.lang.Number]
+ [x y] (clojure.core/+ x y))
+
+(defmethod - [::unary java.lang.Number]
+ [x] (clojure.core/- x))
+
+(defmethod * [::binary java.lang.Number]
+ [x y] (clojure.core/* x y))
+
+(defmethod / [::unary java.lang.Number]
+ [x] (clojure.core// x))
+
diff --git a/src/clojure/contrib/load_all.clj b/src/clojure/contrib/load_all.clj
index 94bc8e91..f2b77bac 100644
--- a/src/clojure/contrib/load_all.clj
+++ b/src/clojure/contrib/load_all.clj
@@ -42,6 +42,7 @@ duck-streams
error-kit
except
fcase
+generic.arithmetic
import-static
javadoc.browse
javadoc