summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2009-01-21 00:27:43 +0000
committerRich Hickey <richhickey@gmail.com>2009-01-21 00:27:43 +0000
commit5d0ac342b80b5f60b9d2e9986c0c601f6cba0674 (patch)
treede9050ca1796d021c1ab1d4d04fc6c95f50f8074
parent06d3b59c23ef90c9410470652ed6fc408d360716 (diff)
added methods/prefers for multimethod reflection
-rw-r--r--src/clj/clojure/core.clj8
-rw-r--r--src/jvm/clojure/lang/MultiFn.java24
2 files changed, 23 insertions, 9 deletions
diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj
index 1b0d1484..1285dd2c 100644
--- a/src/clj/clojure/core.clj
+++ b/src/clj/clojure/core.clj
@@ -1026,6 +1026,14 @@
[multifn dispatch-val-x dispatch-val-y]
(. multifn preferMethod dispatch-val-x dispatch-val-y))
+(defn methods
+ "Given a multimethod, returns a map of dispatch values -> dispatch fns"
+ [multifn] (.getMethodTable multifn))
+
+(defn prefers
+ "Given a multimethod, returns a map of preferred value -> set of other values"
+ [multifn] (.getPreferTable multifn))
+
;;;;;;;;; var stuff
(defmacro #^{:private true} assert-args [fnname & pairs]
diff --git a/src/jvm/clojure/lang/MultiFn.java b/src/jvm/clojure/lang/MultiFn.java
index ee007efc..bb818da4 100644
--- a/src/jvm/clojure/lang/MultiFn.java
+++ b/src/jvm/clojure/lang/MultiFn.java
@@ -13,7 +13,6 @@
package clojure.lang;
import java.util.Map;
-import java.util.Collection;
public class MultiFn extends AFn{
final public IFn dispatchFn;
@@ -33,19 +32,19 @@ public MultiFn(IFn dispatchFn, Object defaultDispatchVal) throws Exception{
this.dispatchFn = dispatchFn;
this.defaultDispatchVal = defaultDispatchVal;
this.methodTable = PersistentHashMap.EMPTY;
- this.methodCache = methodTable;
+ this.methodCache = getMethodTable();
this.preferTable = PersistentHashMap.EMPTY;
cachedHierarchy = null;
}
synchronized public MultiFn addMethod(Object dispatchVal, IFn method) throws Exception{
- methodTable = methodTable.assoc(dispatchVal, method);
+ methodTable = getMethodTable().assoc(dispatchVal, method);
resetCache();
return this;
}
synchronized public MultiFn removeMethod(Object dispatchVal) throws Exception{
- methodTable = methodTable.without(dispatchVal);
+ methodTable = getMethodTable().without(dispatchVal);
resetCache();
return this;
}
@@ -54,7 +53,7 @@ synchronized public MultiFn preferMethod(Object dispatchValX, Object dispatchVal
if(prefers(dispatchValY, dispatchValX))
throw new IllegalStateException(
String.format("Preference conflict: %s is already preferred to %s", dispatchValY, dispatchValX));
- preferTable = preferTable.assoc(dispatchValX, RT.conj((IPersistentCollection) RT.get(preferTable,
+ preferTable = getPreferTable().assoc(dispatchValX, RT.conj((IPersistentCollection) RT.get(getPreferTable(),
dispatchValX,
PersistentHashSet.EMPTY),
dispatchValY));
@@ -63,7 +62,7 @@ synchronized public MultiFn preferMethod(Object dispatchValX, Object dispatchVal
}
private boolean prefers(Object x, Object y) throws Exception{
- IPersistentSet xprefs = (IPersistentSet) preferTable.valAt(x);
+ IPersistentSet xprefs = (IPersistentSet) getPreferTable().valAt(x);
if(xprefs != null && xprefs.contains(y))
return true;
for(ISeq ps = RT.seq(parents.invoke(y)); ps != null; ps = ps.rest())
@@ -88,7 +87,7 @@ private boolean dominates(Object x, Object y) throws Exception{
}
private IPersistentMap resetCache(){
- methodCache = methodTable;
+ methodCache = getMethodTable();
cachedHierarchy = hierarchy.get();
return methodCache;
}
@@ -102,7 +101,7 @@ synchronized private IFn getFn(Object dispatchVal) throws Exception{
targetFn = findAndCacheBestMethod(dispatchVal);
if(targetFn != null)
return targetFn;
- targetFn = (IFn) methodTable.valAt(defaultDispatchVal);
+ targetFn = (IFn) getMethodTable().valAt(defaultDispatchVal);
if(targetFn == null)
throw new IllegalArgumentException(String.format("No method for dispatch value: %s", dispatchVal));
return targetFn;
@@ -110,7 +109,7 @@ synchronized private IFn getFn(Object dispatchVal) throws Exception{
private IFn findAndCacheBestMethod(Object dispatchVal) throws Exception{
Map.Entry bestEntry = null;
- for(Object o : methodTable)
+ for(Object o : getMethodTable())
{
Map.Entry e = (Map.Entry) o;
if(isA(dispatchVal, e.getKey()))
@@ -289,4 +288,11 @@ public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object
arg15, arg16, arg17, arg18, arg19, arg20, args);
}
+ public IPersistentMap getMethodTable() {
+ return methodTable;
+ }
+
+ public IPersistentMap getPreferTable() {
+ return preferTable;
+ }
}