我希望创建一个抽象,代表一个数据库表,但可以使用所有常规的Clojure seq、conj等操作。我需要添加协议吗?
我希望创建一个抽象,代表一个数据库表,但可以使用所有常规的Clojure seq、conj等操作。我需要添加协议吗?
是的。这个协议是由Java接口 clojure.lang.ISeq
定义的。你可能想要扩展 clojure.lang.ASeq
,它提供了一个抽象实现。
这里有一个例子:一个可关闭的资源的 seq
抽象,在 seq
结束时自动关闭。(未经严格测试)
(deftype CloseableSeq [delegate-seq close-fn]
clojure.lang.ISeq
(next [this]
(if-let [n (next delegate-seq)]
(CloseableSeq. n close-fn)
(.close this)))
(first [this] (if-let [f (first delegate-seq)] f (.close this)))
(more [this] (if-let [n (next this)] n '()))
(cons [this obj] (CloseableSeq. (cons obj delegate-seq) close-fn))
(count [this] (count delegate-seq))
(empty [this] (CloseableSeq. '() close-fn))
(equiv [this obj] (= delegate-seq obj))
clojure.lang.Seqable
(seq [this] this)
java.io.Closeable
(close [this] (close-fn)))
seq
的实现似乎不正确,因为当在空序列上调用 seq
时,seq
应该返回 nil,但这里你只是返回原始序列。 - Shantanu Kumar