そこにアトムを持つ型を定義する次のコードがあります。
(defprotocol IDeck
(vec-* [dk] "永続ベクトルへの出力")
(count-* [dk] "デッキ内の要素数")
(conj1-* [dk & es] "デッキに複数の要素を追加する"))
(deftype ADeck [#^clojure.lang.Atom val]
IDeck
(vec-* [dk] (->> (.val dk) deref (map deref) vec))
(count-* [dk] (-> (.val dk) deref count))
(conj1-* [dk & es]
(試す
(ループ [ES]
(let [e (最初の esi)]
(状態
(なし? e) dk
:そうしないと
(行う
(swap! (.val dk) #(conj % (atom e)))
(繰り返し (残りの esi))))))
(catch Throwable t (println t)))))
(defn new-*adeck
([] (ADeck. (atom [])))
([v] (ADeck. (atom (vec (map atom v))))))
(defn conj2-* [dk & es]
(試す
(ループ [ES]
(let [e (最初の esi)]
(状態
(なし? e) dk
:そうしないと
(行う
(swap! (.val dk) #(conj % (atom e)))
(繰り返し (残りの esi))))))
(catch Throwable t (println t))))
;; 使用法
(def a (new-*adeck [1 2 3 4]))
(count-* a)
;=> 4
(vec-* a)
;=> [1 2 3 4]
(conj1-* a 1 2) ;; deftype ケース
;=> IllegalArgumentException java.lang.IllegalArgumentException: 次から ISeq を作成する方法がわかりません: java.lang.Long
(vec-* a)
;=> [1 2 3 4]
(conj2-* a 1 2) ;; 定義されたケース
(vec-* a)
;=> [1 2 3 4 1 2]
2 つの conj-* メソッドはまったく同じですが、1 つは deftype で、もう 1 つは通常の defn であることを除いて、最初のメソッドはエラーを返し、2 番目のメソッドは成功します。どうしてこれなの?