Сохранение + чтение отсортированных карт в файл в Clojure
Я сохраняю вложенную карту данных на диск через spit
, Я хочу, чтобы некоторые карты внутри моей карты сортировались и оставались отсортированными, когда я slurp
карта обратно в мою программу. Сортированные карты не имеют уникального буквального представления, поэтому, когда я spit
карта карт на диске, отсортированные карты и несортированные карты представлены одинаково, и #(read-string (slurp %))
Использование данных делает каждую карту обычным несортированным типом. Вот игрушечный пример, иллюстрирующий проблему:
(def sorted-thing (sorted-map :c 3 :e 5 :a 1))
;= #'user/sorted-thing
(spit "disk" sorted-thing)
;= nil
(def read-thing (read-string (slurp "disk")))
;= #'user/read-thing
(assoc sorted-thing :b 2)
;= {:a 1, :b 2, :c 3, :e 5}
(assoc read-thing :b 2)
;= {:b 2, :a 1, :c 3, :e 5}
Есть ли какой-нибудь способ прочитать карты как отсортированные в первую очередь, вместо преобразования их в отсортированные карты после чтения? Или это признак того, что я должен использовать какую-то реальную базу данных?
2 ответа
*print-dup*
динамически перебираемый Var предназначен для поддержки этого варианта использования:
(binding [*print-dup* true]
(prn (sorted-map :foo 1)))
; #=(clojure.lang.PersistentTreeMap/create {:foo 1})
Закомментированная строка - это то, что печатается.
Так получилось, что это тоже влияет str
применительно к структурам данных Clojure, и, следовательно, также spit
так что если вы делаете
(binding [*print-dup* true]
(spit "foo.txt" (sorted-map :foo 1)))
представление карты, записанное в foo.txt
будет отображаться выше.
Правда, я не уверен на 100%, задокументировано ли это где-то; если вы чувствуете себя неловко по этому поводу, вы всегда можете spit
результат использования pr-str
с *print-dup*
связан с true
:
(binding [*print-dup* true]
(pr-str (sorted-map :foo 1)))
;= "#=(clojure.lang.PersistentTreeMap/create {:foo 1})"
(На этот раз последняя строка - это возвращаемое значение, а не вывод на печать.)
Очевидно, вам придется иметь *read-eval*
связан с true
чтобы иметь возможность читать обратно эти литералы. Это хорошо, хотя, это именно то, для чего он предназначен (чтение кода из надежных источников).
Я не думаю, что это обязательно знак того, что вы должны использовать базу данных, но я думаю, что это признак того, что вы не должны использовать spit
, Когда вы записываете отсортированные карты на диск, не используйте буквальный синтаксис карты. Если вы напишите его в следующем формате, будет работать read-string:
(def sorted-thing (eval (read-string "(sorted-map :c 3 :e 5 :a 1)")))
(assoc sorted-thing :b 2)
;= {:a 1, :b 2, :c 3, :e 5}