Reputation: 14258
I have the following code, defining a type that has an atom in there.
(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]
Even though the two conj-* methods are exactly the same, except that one is in a deftype and the other is a normal defn, the first gives an error while the second succeeds. Why is this?
Upvotes: 2
Views: 183
Reputation: 33637
This is because protocols doesn't support variable number of arguments.
What you can do is make:
(conj1-* [dk & es] "Adding multiple elements to the deck"))
into
(conj1-* [dk es] "Adding multiple elements to the deck"))
such that the es param will be vector and called like:
(conj1-* a [1 2])
Upvotes: 2