2012-02-14 14 views
5

Sto creando un'interfaccia Clojure su un'API Java con un metodo che restituisce un java.util.LinkedHashSet.Conversione di raccolte Java in strutture dati Clojure

In primo luogo, il modo clojure idiomatico di gestirlo per convertire il LinkedHashSet in una struttura dati clojure?

In secondo luogo, qual è il metodo migliore per convertire le raccolte Java in strutture di dati Clojure?

risposta

12

Ci sono un sacco di opzioni, dal momento che Clojure gioca molto bene con collezioni di Java. Dipende esattamente da quale struttura dati si desidera utilizzare in Clojure.

Ecco alcuni esempi:

;; create a HashSet 
(def a (java.util.HashSet.)) 
(dotimes [i 10] (.add a i)) 

;; Get all the values as a sequence 
(seq a) 
=> (0 1 2 3 4 5 6 7 8 9) 

;; build a new HashSet containing the values from a 
(into #{} a) 
#{0 1 2 3 4 5 6 7 8 9} 

;; Just use the HashSet directly (high performance, no copy required) 
(.contains a 1) 
=> true 
(.contains a 100) 
=> false 

Per quanto riguarda quando utilizzare ciascuna di queste, suggerirei il seguente consiglio:

  • Se si sta tentando di avvolgere una libreria Java e presentare un pulito Clojure API, quindi suggerirei di convertire le strutture di dati Clojure equivalenti. Questo è ciò che gli utenti Clojure si aspettano, e puoi nascondere i dettagli dell'interop di Java potenzialmente disordinati. Come bonus, questo renderà le cose immutabili in modo da non correre il rischio che le collezioni Java si mutino mentre le usi.
  • Se si desidera utilizzare l'API Java in modo rapido ed efficiente, è sufficiente utilizzare l'interoperabilità Java direttamente nelle raccolte Java.
2

Il modo idiomatico per convertire le raccolte java in clojure consiste nell'utilizzare la funzione (seq), che è già chiamata dalla maggior parte delle funzioni che operano su sequenze.

(def s (java.util.LinkedHashSet.)) 
#'user/s 
user> (seq s) 
nil 
user> (.add s "foo") 
true 
user> (seq s) 
("foo") 
user> 
2

Sinceramente non so se c'è una pratica universalmente accettata, ma ecco Chris Houser arguing contro Java per adattatori Clojure come si rompe la compatibilità con le API Java originale.

Per eseguire la traduzione che hai chiesto, è sufficiente utilizzare into:

user=> (import java.util.LinkedHashSet) 
java.util.LinkedHashSet 
user=> (def x (LinkedHashSet.)) 
#'user/x 
user=> (.add x "test") 
true 
user=> (def y (into #{} x)) 
#'user/y 
user=> y 
#{"test"}