Преобразование коллекций Java в структуры данных Clojure

Я создаю интерфейс Clojure для API Java с методом, который возвращает java.util.LinkedHashSet.

Во-первых, является ли идиоматический способ обработки Clojure для преобразования LinkedHashSet в структуру данных clojure?

Во-вторых, как лучше всего преобразовать коллекции Java в структуры данных Clojure?


person Toby Hede    schedule 14.02.2012    source источник


Ответы (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 во время их использования.
  • Если вы просто хотите быстро и эффективно использовать API Java, просто используйте взаимодействие Java непосредственно с коллекциями Java.
person mikera    schedule 14.02.2012

Идиоматический способ преобразования коллекций Java в clojure — использовать функцию (seq), которая уже вызывается большинством функций, работающих с последовательностями.

(def s (java.util.LinkedHashSet.))
#'user/s
user> (seq s)
nil
user> (.add s "foo")
true
user> (seq s)
("foo")
user> 
person Joost Diepenmaat    schedule 14.02.2012

Честно говоря, я не знаю, существует ли общепринятая практика, но вот Крис Хаузер спорит против адаптеров Java-Clojure, поскольку вы нарушаете совместимость с исходным Java API.

Чтобы выполнить перевод, о котором вы просили, просто используйте 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"}
person skuro    schedule 14.02.2012