Преобразование коллекций 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"}
Другие вопросы по тегам