2

そこにアトムを持つ型を定義する次のコードがあります。

(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 番目のメソッドは成功します。どうしてこれなの?

4

1 に答える 1

2

これは、プロトコルが可変数の引数をサポートしていないためです。

あなたができることは作ることです:

(conj1-*  [dk & es] "Adding multiple elements to the deck"))

の中へ

(conj1-*  [dk es] "Adding multiple elements to the deck"))

es paramがベクトルになり、次のように呼び出されるようにします。

(conj1-* a [1 2])
于 2012-08-29T04:45:43.327 に答える