2012-02-10 16 views
12

Sto usando la libreria Sesame per eseguire query SPARQL su un triplo store in memoria.Come trasformare un oggetto java Iterator in una sequenza di clojure

Sto usando Clojure per raggiungere questo obiettivo.

Un risultato di query è un oggetto personalizzato simile a Iterator [1], pertanto il clojure seq non funziona immediatamente.

Qual è il modo più elegante per trasformare un oggetto java Iterator personalizzato in una sequenza di clojure?

L'idea più ovvia e stupida che mi è venuta in mente è quella di ricollegarlo e creare un vettore clojure, ma sono sicuro che c'è un approccio più elegante a questo problema.

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

risposta

8

La versione testata:

(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))))))) 
+2

Questo (reiterare Iterable invece di Iterator) è un approccio; un altro è reificare Iterator e quindi avvolgerlo con ['iterator-seq'] (http://clojuredocs.org/clojure_core/clojure.core/iterator-seq). – amalloy

+0

Bello, buono a sapersi! – laczoka

5

ne dite di avvolgere l'oggetto iteratore-come in un oggetto che implementa l'interfaccia in realtà Iterator? Qualcosa di simile a quanto segue (non testato):

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

Per quanto posso dire, l'unico vantaggio (se si vuole chiamare così) dell'interfaccia Iteration sopra l'interfaccia standard Iterator è che permette di dichiarare controllate eccezioni, che non sono comunque utilizzate in Clojure.

[Aggiornamento: Corretto codice per utilizzare iterator-seq invece di seq, come suggerito da @amalloy in un commento su un'altra risposta.]

+0

Grazie. Non proprio, ma mi ha indirizzato nella giusta direzione e mi ha aiutato a conoscere l'uso pratico di * reify *. – laczoka

+0

Ho già una versione corretta testata, non posso ancora auto-rispondere a causa di alcune restrizioni sulla reputazione. :) – laczoka

1

Pure funzionale iterabile-to codice pigro-sequenza per Java Iterable e Iterator

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

per iteratori personalizzati sostituire .iterator, .hasNext e chiamate .Next.

Il vantaggio è che è puramente funzionale poiché richiede un argomento come argomento. Altre soluzioni postate accettano un argomento iteratore che è mutabile, quindi la funzione può restituire una sequenza diversa a seconda dello stato iteratore interno che viola lo referential transparency. La funzione è anche fiammeggiante per la sua pigrizia.

1

Perché non provare con lo 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. 

Come si può vedere nella docstring sopra, si potrebbe anche non essere necessario utilizzare iterator-seq in modo esplicito. Hai appena provato a considerare il tuo iteratore Java come una sequenza nel REPL?

+0

Questo non funziona poiché iterator-seq funziona esplicitamente solo con java.util.Iterator, mentre l'oggetto qui descritto è un info.aduna.iteration.Iteration. L'utilizzo di iteratore-seq porta a ClassCastException. – PaulaG

Problemi correlati