我有以下代码,定义了一个里面有一个原子的类型。
(定义协议 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 之外,第一个给出错误而第二个成功。为什么是这样?