5

我正在通过 . 将嵌套的数据映射保存到磁盘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}

是否有某种方法可以首先按排序读取地图,而不是在阅读后将它们转换为排序地图?或者这是否表明我应该使用某种真实的数据库?

4

2 回答 2

4

我不认为它一定是你应该使用数据库的标志,但我确实认为它是你不应该使用的标志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}
于 2013-06-27T16:08:38.290 回答
4

动态可重新绑定的*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-strwith *print-dup*bound to的结果true

(binding [*print-dup* true]
  (pr-str (sorted-map :foo 1)))
;= "#=(clojure.lang.PersistentTreeMap/create {:foo 1})"

(这次最后一行是返回值而不是打印输出。)

显然,您必须必须*read-eval*能够true读回这些文字。不过这很好,这正是它的目的(从可信来源读取代码)。

于 2013-06-27T22:06:21.103 回答