Как превратить java Iterator-подобный объект в последовательность замыкания - PullRequest
13 голосов
/ 10 февраля 2012

Я использую библиотеку Sesame для запуска запросов SPARQL над тройным хранилищем в памяти.

Я использую Clojure для достижения этой цели.

Результатом запроса является пользовательский объект, подобный Iterator [1], поэтому clojure seq не работает с ним из коробки.

Какой самый элегантный способ превратить пользовательский Java-подобный итератор в замкнутую последовательность?

Самая очевидная и глупая идея, которая пришла мне в голову, - это обойти ее и создать вектор замыкания, но я уверен, что есть более элегантный подход к этой проблеме.

[1] http://www.openrdf.org/doc/sesame2/api/info/aduna/iteration/Iteration.html

Ответы [ 4 ]

10 голосов
/ 10 февраля 2012

Протестированная версия:

(defn iteration->seq [iteration]
 (seq
  (reify java.lang.Iterable 
      (iterator [this] 
         (reify java.util.Iterator
           (hasNext [this] (.hasNext iteration))
           (next [this] (.next iteration))
           (remove [this] (.remove iteration)))))))
7 голосов
/ 10 февраля 2012

Как насчет обертывания объекта, подобного итератору, в объекте, который фактически реализует интерфейс Iterator? Что-то вроде следующего (не проверено):

(defn iteration-seq [iteration]
  (iterator-seq
   (reify java.util.Iterator
     (hasNext [this] (.hasNext iteration))
     (next [this] (.next iteration))
     (remove [this] (.remove iteration)))))

Насколько я могу судить, единственное преимущество (если вы хотите так его назвать) интерфейса Iteration перед стандартным интерфейсом Iterator состоит в том, что он позволяет объявлять проверенные исключения, которые не используются в Clojure. в любом случае.

[Обновление: исправлен код для использования iterator-seq вместо seq, как предложил @amalloy в комментарии к другому ответу.]

2 голосов
/ 07 июля 2013

Почему бы не попробовать clojure.core / iterator-seq ?

user=> (doc iterator-seq)
-------------------------
clojure.core/iterator-seq
([iter])
  Returns a seq on a java.util.Iterator. Note that most collections
  providing iterators implement Iterable and thus support seq directly.

Как вы можете видеть в приведенной выше строке документации, вам даже не нужно явно использовать iterator-seq. Вы только что попытались обработать свой Java-итератор как последовательность в REPL?

1 голос
/ 26 марта 2013

Чистый функциональный код итеративной-ленивой последовательности для java Iterable и Iterator

(defn iter-seq
  ([iterable] 
    (iter-seq iterable (.iterator iterable)))
  ([iterable i] 
    (lazy-seq 
      (when (.hasNext i)
        (cons (.next i) (iter-seq iterable i))))))

Для пользовательских итераторов замените вызовы .iterator, .hasNext и .next.

Преимущество состоит в том, что он является чисто функциональным, поскольку он принимает итеративный аргумент.Другие опубликованные решения принимают аргумент итератора, который является изменяемым, поэтому функция может возвращать другую последовательность в зависимости от внутреннего состояния итератора, что нарушает ссылочную прозрачность .Эта функция также ярка из-за своей лени.

...