我有以下代码,定义了一个里面有一个原子的类型。
(定义协议 IDeck
(vec-* [dk] "输出到持久向量")
(count-* [dk] "甲板上的元素数量")
(conj1-* [dk & es] "向牌组添加多个元素"))
(deftype ADeck [#^clojure.lang.Atom val]
甲板
(vec-* [dk] (->> (.val dk) deref (map deref) vec))
(count-* [dk] (-> (.val dk) deref count))
(conj1-* [dk & es]
(尝试
(循环[esi es]
(让[e(第一个esi)]
(条件
(nil?e) dk
:别的
(做
(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]
(尝试
(循环[esi es]
(让[e(第一个esi)]
(条件
(nil?e) dk
:别的
(做
(swap! (.val dk) #(conj % (atom e)))
(recur (rest esi))))))
(catch Throwable t (println t))))
;; 用法
(def a (new-*adeck [1 2 3 4]))
(计数-* a)
;=> 4
(vec-* a)
;=> [1 2 3 4]
(conj1-* a 1 2) ;; deftype 案例
;=> IllegalArgumentException java.lang.IllegalArgumentException:不知道如何从:java.lang.Long 创建 ISeq
(vec-* a)
;=> [1 2 3 4]
(conj2-* a 1 2) ;; 定义案例
(vec-* a)
;=> [1 2 3 4 1 2]
尽管这两个 conj-* 方法完全相同,除了一个是 deftype 而另一个是普通 defn 之外,第一个给出错误而第二个成功。为什么是这样?