我有以下代码,定义了一个其中包含原子的类型。
(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,但第一个会出错,而第二个会成功。这是为什么?
最佳答案
这是因为协议(protocol)不支持可变数量的参数。
你能做的是:
(conj1-* [dk & es] "Adding multiple elements to the deck"))
进入
(conj1-* [dk es] "Adding multiple elements to the deck"))
这样 es 参数将是向量并调用如下:
(conj1-* a [1 2])
关于clojure - 在 deftype 中使用原子时出现奇怪的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12169508/