2016-09-30 46 views
2

我希望能够采取多种方法,将其作为独立变量克隆并添加到它,而无需更改原始内容。如何才能做到这一点?是否可以克隆multimethod?

(defmulti hello :type) 

(defmethod hello :a 
    [e] (assoc e :a 1)) 

(hello {:type :a}) 
=> {:type :a :a 1} 

;; my attempt at cloning 
(def world @#'hello) 

(defmethod world :b 
    [e] (assoc e :b 2)) 

(world {:type :b}) 
=> {:type :b :b 2} 

;; I want this to throw... but because `hello` and `world` 
;; are the same function, it still works 
(hello {:type :b}) 
=> {:type :b :b 2} 

回答

2

想通了通过看https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L1769-L1777

(defn clone 
    [multi name] 
    (let [table (.getMethodTable multi) 
     clone (clojure.lang.MultiFn. name 
            (.dispatchFn multi) 
            (.defaultDispatchVal multi) 
            (.hierarchy multi)] 
    (doseq [[dispatch-val method] table] 
     (.addMethod clone dispatch-val method)) 
    clone)) 

----回到原来的问题----

(defmulti hello :type) 

(defmethod hello :a 
    [e] (assoc e :a 1)) 

(def world (clone hello "world")) 

(defmethod world :b 
    [e] (assoc e :b 2)) 

(world {:type :b}) 
=> {:type :b :b 2} 

(hello {:type :b}) 
=> (throws) 
相关问题