Make Java class work as a sequence in Clojure

I am using a Java class that represents a sequence of results (somewhat like a Clojure vector).

I would like to use this class with typical Clojure sequence functions (i.e. I want the class to behave as if it supported sequence abstraction), however I cannot change the class so I cannot implement it clojure.lang.Seqable or similar. Also, annoyingly, the class does not implement java.util.Collection or java.lang.Iterable .

I see several options:

  • Use iterator-seq for the (existing) iterator object.
  • Wrap the object in another class that implements java.util.Collection / clojure.lang.Sequable
  • Create a function that builds a vector or Clojure sequence by querying an object

Are there any other options? What is the best approach?

+8
java clojure sequence
source share
3 answers

The fastest and easiest way is to use iterator-seq .

This begs the question: why does core Clojure not provide a protocol such as SeqSource that seq will invoke. Non-standard collections can then be β€œextended” to provide seq, similar to how InternalReduce works for reduce .

+6
source share

Use proxy to extend the class and implement its ISeq

+6
source share

My first shot would be to create a lazy-seq of this object:

 (defn sequify [obj] (letfn [(inner [idx] (when (< idx (.size obj)) (cons (.get obj idx) (lazy-seq (inner (inc idx))))))] (inner 0))) 

Just replace .size and .get with the appropriate methods.

Writing a wrapper might be more appropriate if you want to improve performance over the lazy-seq solution.

+2
source share

All Articles