Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Clojure how can I implement standard Clojure collection interfaces on my own records and types?

Tags:

clojure

I wish to create an abstraction which represents a database table, but which can be accessed using all the usual Clojure seq and conj and all that fancy stuff. Is there a protocol I need to add?

like image 488
yazz.com Avatar asked Jan 03 '11 17:01

yazz.com


1 Answers

Yes. The protocol is defined by the Java interface clojure.lang.ISeq. You may want to extend clojure.lang.ASeq which provides an abstract implementation of it.

Here is an example: a seq abstraction of a resource which is closable and is closed automatically when the seq ends. (Not rigorously tested)

(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)))
like image 95
Abhinav Sarkar Avatar answered Oct 01 '22 06:10

Abhinav Sarkar