2012-08-29 61 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]) 
相關問題