Frage

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 the typical Clojure sequence functions (i.e. I want to have the class behave as if it supported the sequence abstraction) however I can't change the class so am unable to make it implement clojure.lang.Seqable or similar. Also, annoyingly, the class does not implement java.util.Collection or java.lang.Iterable.

I can see a few options:

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

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

War es hilfreich?

Lösung

The fastest and most straightforward would be to use iterator-seq.

This does beg the question: Why doesn't core Clojure provide a protocol like SeqSource that would be called by seq. Then non-standard collections could be "extended" to supply a seq, similar to how the InternalReduce works for reduce.

Andere Tipps

Use proxy to extend the class and make it implement ISeq

My first shot would be to create lazy-seq of that 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 appropriate methods.

Writing a wrapper may be more appropriate if you want to improve performance compared to lazy-seq solution.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top