2

我有以下代码,定义了一个里面有一个原子的类型。

(定义协议 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 之外,第一个给出错误而第二个成功。为什么是这样?

4

1 回答 1

2

这是因为协议不支持可变数量的参数。

你可以做的是:

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

进入

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

这样 es 参数将是向量并被称为:

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