2012-08-29 2 views
2

다음 코드를 사용하여 원자가있는 유형을 정의합니다. 그 하나는 DEFTYPE이고 다른 하나는 정상 defn이 점을 제외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- * 방법은 제 성공하면서 제 오류를 제공 똑같은 비록. 왜 이런거야?

답변

2

이것은 프로토콜이 다양한 수의 인수를 지원하지 않기 때문입니다.

은 당신이 할 수있는 일은 할 수 있습니다 :

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

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

배아 줄기 PARAM 벡터와 같이 호출됩니다 있도록 :

(conj1-* a [1 2]) 
관련 문제