2012-08-29 39 views
2

我有以下代码,定义了一个在其中有原子的类型。在deftype中使用原子时出现奇怪的错误

 
(defprotocol IDeck 
    (vec-* [dk] "Output to a persistent vector") 
    (count-* [dk] "Number of elements in the deck") 
    (conj1-* [dk & es] "Adding multiple elements to the deck")) 


(deftype ADeck [#^clojure.lang.Atom val] 
    IDeck 
    (vec-* [dk] (->> (.val dk) deref (map deref) vec)) 

    (count-* [dk] (-> (.val dk) deref count)) 

    (conj1-* [dk & es] 
    (try 
     (loop [esi es] 
     (let [e (first esi)] 
      (cond 
      (nil? e) dk 
      :else 
      (do 
       (swap! (.val dk) #(conj % (atom e))) 
       (recur (rest esi)))))) 
     (catch Throwable t (println t))))) 

(defn new-*adeck 
    ([] (ADeck. (atom []))) 
    ([v] (ADeck. (atom (vec (map atom v)))))) 

(defn conj2-* [dk & es] 
    (try 
    (loop [esi es] 
     (let [e (first esi)] 
     (cond 
      (nil? e) dk 
      :else 
      (do 
      (swap! (.val dk) #(conj % (atom e))) 
      (recur (rest esi)))))) 
    (catch Throwable t (println t)))) 


;; Usage 
(def a (new-*adeck [1 2 3 4])) 

(count-* a) 
;=> 4 

(vec-* a) 
;=> [1 2 3 4] 

(conj1-* a 1 2) ;; The deftype case 
;=> IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long 

(vec-* a) 
;=> [1 2 3 4] 

(conj2-* a 1 2) ;; The defn case 
(vec-* a) 
;=> [1 2 3 4 1 2] 

即使两个conj- *方法是完全一样的,不同之处在于一个处于DEFTYPE和另一个是正常DEFN,而第二个成功,则第一给出了一个错误。为什么是这样?

回答

2

这是因为协议不支持可变数量的参数。

你可以做的就是令:

(conj1-* [dk & es] "Adding multiple elements to the deck")) 

(conj1-* [dk es] "Adding multiple elements to the deck")) 

使得ES PARAM将是矢量,并呼吁像:

(conj1-* a [1 2]) 
相关问题