Преобразование коллекций Java в структуры данных Clojure
Я создаю интерфейс Clojure для Java API с методом, который возвращает java.util.LinkedHashSet.
Во-первых, является ли идиоматический способ Clojure обрабатывать это для преобразования LinkedHashSet в структуру данных clojure?
Во-вторых, каков наилучший метод для преобразования коллекций Java в структуры данных Clojure?
3 ответа
Вариантов много, так как Clojure очень хорошо работает с коллекциями Java. Это зависит от того, какую именно структуру данных вы хотите использовать в Clojure.
Вот несколько примеров:
;; 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
Что касается того, когда использовать каждый из них, я бы предложил следующий совет:
- Если вы пытаетесь обернуть библиотеку Java и представить чистый API Clojure, то я бы предложил преобразовать в эквивалентные структуры данных Clojure. Это то, что ожидают пользователи Clojure, и вы можете скрыть потенциально грязные детали взаимодействия Java. В качестве бонуса, это сделает вещи неизменными, так что вы не рискуете поменять коллекции Java во время их использования.
- Если вы просто хотите использовать Java API быстро и эффективно, просто используйте взаимодействие Java непосредственно с коллекциями Java.
Идиоматический способ преобразования java-коллекций в clojure заключается в использовании функции (seq), которая уже вызывается большинством функций, работающих с последовательностями.
(def s (java.util.LinkedHashSet.))
#'user/s
user> (seq s)
nil
user> (.add s "foo")
true
user> (seq s)
("foo")
user>
Честно говоря, я не знаю, есть ли общепринятая практика, но здесь Крис Хаузер спорит против адаптеров Java к Clojure, поскольку вы нарушаете совместимость с оригинальным Java API.
Чтобы выполнить перевод, который вы просили, просто используйте в:
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"}