Если вы хотите сериализовать вещи в S-выражения, вы можете использовать print-dup
:
(binding [*print-dup* true] (println [1 2 3]))
; prints [1 2 3]
(defrecord Foo [x])
; => user.Foo
(binding [*print-dup* true] (println (Foo. :foo)))
; prints #=(user.Foo/create {:x :foo})
Обратите внимание, что печать структуры, которая содержит, скажем, десять ссылок на один вектор с последующим чтением его обратно, дает вам структуру данных с десятью отдельными (не identical?
), хотя эквивалентными в терминах структурных (=
) векторами .
Чтобы использовать это в тех случаях, когда не предусмотрена реализация по умолчанию, реализуйте мультиметод clojure.core/print-dup
.
Кроме того, в Clojure 1.2 есть много вещей, которые java.io.Serializable
:
(every? (partial instance? java.io.Serializable)
[{1 2} #{"asdf"} :foo 'foo (fn [] :foo)])
; => true
(defrecord Foo [])
(instance? java.io.Serializable (Foo.))
; => true
Обратите внимание, что вам следует избегать сериализации созданных во время выполнения fn
s - они являются экземплярами одноразовых классов со странными именами, и вы не сможете десериализовать их после перезапуска JVM в любом случае. С компиляцией AOT fn
s получают свои собственные фиксированные имена классов.
Обновление: Как уже упоминалось в комментарии к вопросу, Serializable
лучше всего подходит для кратковременного хранения / передачи данных, тогда как print-dup
должно быть более устойчивым в качестве долговременного хранилища. решение (работает во многих версиях приложения, Clojure и т. д.). Причина в том, что print-dup
никак не зависит от структуры сериализуемых классов (поэтому вектор print-dup
'd сегодня будет по-прежнему читаемым, когда реализация вектора переключится с Java на Clojure deftype
).