summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2007-10-20 20:09:54 +0000
committerRich Hickey <richhickey@gmail.com>2007-10-20 20:09:54 +0000
commitfe567065b55b47705a6292e6f993001e4ef31997 (patch)
tree15e20f261c9844d1944dbfa56f33d08789d29fe0 /src
parent068bc4439d03127b78cf223504a626dbd05e6b04 (diff)
Multimethods
Diffstat (limited to 'src')
-rw-r--r--src/boot.clj24
-rw-r--r--src/jvm/clojure/lang/MultiFn.java27
2 files changed, 27 insertions, 24 deletions
diff --git a/src/boot.clj b/src/boot.clj
index 012e3a1d..20e7702f 100644
--- a/src/boot.clj
+++ b/src/boot.clj
@@ -296,14 +296,21 @@
([x form] `(. ~x ~form))
([x form & more] `(.. (. ~x ~form) ~@more)))
-;;polyfns
-(defmacro defpolyfn [name dispatch-fn]
- `(def ~name (new clojure.lang.PolyFn ~dispatch-fn)))
+;;multimethods
+(defmacro defmulti
+ ([name dispatch-fn] (thisfn name dispatch-fn :default))
+ ([name dispatch-fn default-val]
+ `(def ~name (new clojure.lang.MultiFn ~dispatch-fn ~default-val))))
-(defmacro defmethod [polyfn dispatch-val & fn-tail]
- `(let [pvar# (the-var ~polyfn)]
- (locking pvar#
- (. pvar# (bindRoot (.. pvar# (getRoot) (assoc ~dispatch-val (fn ~@fn-tail))))))))
+(defmacro defmethod [multifn dispatch-val & fn-tail]
+ `(let [pvar# (the-var ~multifn)]
+ (. pvar# (commuteRoot (fn [mf#] (. mf# (assoc ~dispatch-val (fn ~@fn-tail))))))))
+
+(defmacro remove-method [multifn dispatch-val]
+ `(let [pvar# (the-var ~multifn)]
+ (. pvar# (commuteRoot (fn [mf#] (. mf# (dissoc ~dispatch-val)))))))
+
+;;;;;;;;; var stuff
(defmacro binding [bindings & body]
(let [var-ize (fn [var-vals]
@@ -600,7 +607,8 @@
peek pop nth contains get
assoc dissoc find keys vals merge
rseq sym name namespace locking ..
- defpolyfn defmethod binding find-var
+ defmulti defmethod remove-method
+ binding find-var
ref deref deref! commute set sync
reduce reverse comp appl
every not-every any not-any
diff --git a/src/jvm/clojure/lang/MultiFn.java b/src/jvm/clojure/lang/MultiFn.java
index a122b199..53c0b8d5 100644
--- a/src/jvm/clojure/lang/MultiFn.java
+++ b/src/jvm/clojure/lang/MultiFn.java
@@ -14,48 +14,43 @@ package clojure.lang;
public class MultiFn extends AFn{
final public IFn dispatchFn;
-final public IFn defaultFn;
+final public Object defaultDispatchVal;
final public IPersistentMap methodTable;
-public MultiFn(IFn dispatchFn, IFn defaultFn){
+public MultiFn(IFn dispatchFn, Object defaultDispatchVal){
this.dispatchFn = dispatchFn;
- this.defaultFn = defaultFn;
+ this.defaultDispatchVal = defaultDispatchVal;
this.methodTable = PersistentHashMap.EMPTY;
}
public MultiFn assoc(Object dispatchVal, IFn method){
- return new MultiFn(meta(), dispatchFn, defaultFn, methodTable.assoc(dispatchVal, method));
+ return new MultiFn(meta(), dispatchFn, defaultDispatchVal, methodTable.assoc(dispatchVal, method));
}
-public MultiFn withDefaultFn(IFn newDefaultFn){
- return new MultiFn(meta(), dispatchFn, newDefaultFn, methodTable);
-}
-public MultiFn without(Object dispatchVal){
- return new MultiFn(meta(), dispatchFn, defaultFn, methodTable.without(dispatchVal));
+public MultiFn dissoc(Object dispatchVal){
+ return new MultiFn(meta(), dispatchFn, defaultDispatchVal, methodTable.without(dispatchVal));
}
public Obj withMeta(IPersistentMap meta){
if(meta == meta())
return this;
- return new MultiFn(meta, dispatchFn, defaultFn, methodTable);
+ return new MultiFn(meta, dispatchFn, defaultDispatchVal, methodTable);
}
-private MultiFn(IPersistentMap meta, IFn dispatchFn, IFn defaultFn, IPersistentMap dispatchTable){
+private MultiFn(IPersistentMap meta, IFn dispatchFn, Object defaultDispatchVal, IPersistentMap dispatchTable){
super(meta);
this.dispatchFn = dispatchFn;
- this.defaultFn = defaultFn;
+ this.defaultDispatchVal = defaultDispatchVal;
this.methodTable = dispatchTable;
}
private IFn getFn(Object dispatchVal) throws Exception{
IFn targetFn = (IFn) methodTable.valAt(dispatchVal);
if(targetFn == null)
- {
- if(defaultFn != null)
- return defaultFn;
+ targetFn = (IFn) methodTable.valAt(defaultDispatchVal);
+ if(targetFn == null)
throw new IllegalArgumentException(String.format("No method for dispatch value: %s", dispatchVal));
- }
return targetFn;
}