Looking for examples of using Java iterators from Clojure...

137 views
Skip to first unread message

stu

unread,
Jul 9, 2011, 5:10:47 AM7/9/11
to Clojure
Hi,

I'd like to make use of Java classes implementing the Java2D
PathIterator interface:

http://download.oracle.com/javase/6/docs/api/java/awt/geom/PathIterator.html

Which leads to a serious impedance mismatch between immutable Clojure
data structures and the iterator's approach of calling next() until
isDone() and using currentSegment() to retrieve the point
coordinates.

I'd guess this kind of iterator is widely used in the Java world, so
can some kind person point to an example of Clojure code using a Java
iterator in this way?

Thanks in advance,

Stu

Jonathan Fischer Friberg

unread,
Jul 9, 2011, 6:49:54 AM7/9/11
to clo...@googlegroups.com
Maybe this would do:
https://gist.github.com/1073506

I should add that I have never used iterators, and that the code is untested ;)

Jonathan

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

David Powell

unread,
Jul 9, 2011, 9:17:27 AM7/9/11
to clo...@googlegroups.com
Clojure has a built in function, iterator-seq, which converts a java.util.Iterator to a lazy-seq.  Lazy-seq's keep a copy of each data item that they have grabbed from the iterator, so they hide the mutability of Iterators.


Your interface doesn't subclass java.util.Iterator though, so you would need to make something similar.

I haven't tested this, but maybe something like this:


(defn pathiterator-seq
  [i]
  (when-not (.isDone i)
    (lazy-seq
     (.next i)
     (let [arr (make-array Double/TYPE 6)
           type (.currentSegment i arr)]
       (cons {:type type :coords (into [] arr)}
             (pathiterator-seq i))))))


-- 
Dave


Jonathan Fischer Friberg

unread,
Jul 9, 2011, 10:08:58 AM7/9/11
to clo...@googlegroups.com
I don't think I like the notion of a lazy-seq and an iterator, since reading the iterator also changes it. Consider the case where you create a lazy-seq from an iterator, and the iterator somehow escapes. Somewhere else the iterator is read from, and now the data that where supposed to be in the lazy-seq no longer exists.

I guess you could clone the iterator, but that would sort of remove the purpose of using a lazy-seq in the first place.

Jonathan

Stuart Halloway

unread,
Jul 9, 2011, 10:27:29 AM7/9/11
to clo...@googlegroups.com
I don't think I like the notion of a lazy-seq and an iterator, since reading the iterator also changes it. Consider the case where you create a lazy-seq from an iterator, and the iterator somehow escapes. Somewhere else the iterator is read from, and now the data that where supposed to be in the lazy-seq no longer exists.

I guess you could clone the iterator, but that would sort of remove the purpose of using a lazy-seq in the first place.

Jonathan

The same argument could apply to every other kind of lazy seq:

* resultset-seq better not let the ResultSet escape
* seqs over arrays better not let the array escape
* line-seq better not let the BufferedReader escape

and so on.

Implementers of seqs are responsible for encapsulating implementation details and not letting them escape. It's a fact of life.

Stu


Stuart Halloway
Clojure/core
http://clojure.com

Jonathan Fischer Friberg

unread,
Jul 9, 2011, 11:47:23 AM7/9/11
to clo...@googlegroups.com
Well, I guess.
But I get the feeling that the iterator are probably coming from some java object somewhere, and might get passed around in that environment, that's why I'm worried.

In the examples you mentioned, line-seq for example. The reader has already 'escaped' since it is passed as an argument. Of course, it is perfectly fine to have a function where the object is completely confined, read-lines[1] in contrib comes to mind.

Functions like line-seq and resultseq-seq are obviously needed somewhere. However, If they are used in conjunction with some java somewhere else...well, I don't like it.

Jonathan

[1] http://clojuredocs.org/clojure_contrib/clojure.contrib.duck-streams/read-lines

Reply all
Reply to author
Forward
0 new messages