我们都知道Rich使用理想的基于哈希树的方法来实现Clojure中的持久数据结构。这种结构使我们能够操作持久数据结构而无需复制很多。
但似乎我找不到正确的方法来序列化这个特定的结构。例如:
(def foo {:a :b :c :d})
(def bar (assoc foo :e :f))
(def bunny {:foo foo :bar bar})
我的问题是:
如何序列化bunny
,以便foo
的内容,即:a
映射到:b
和:c
映射到:d
,在序列化内容中只出现一次?这就像倾倒结构的记忆图像。它也像序列化“内部节点”以及引用here的“叶子节点”。
PS 如果这是相关的,我正在构建一个大的DAG(有向非循环图),我们assoc
将这些节点链接到这些节点并想要序列化DAG用于以后的反序列化。图表的扩展表示(即,在repl中打印DAG时将获得的内容)是不可接受的长。
答案 0 :(得分:1)
Davyzhu,
首先要做的事情很少:
foo
一次或多次,则在打印过程中将依次完全实现(即显示)。编辑:自原始帖子修改后,根据评论澄清但是示例 不反映DAG的层次性。
一个人为的例子:
(def node1 {:a :b :c :d})
(def node2 {:e :f})
(def dictionary {:foo node1 :bar node2})
(def DAG [:bunny [:foo :bar]])
(println DAG) ; => [:bunny [:foo :bar]]
(defn expand-dag1
[x]
(if (keyword? x)
(get dictionary x x)
x))
(println (w/postwalk expand-dag1 DAG)) ; => [:bunny [{:a :b, :c :d} {:e :f}]]
注意:使用向量,地图,列表等来表达您的DAG取决于您。
答案 1 :(得分:1)
这是一个选项(在Clojurescript中不起作用,如果重要的话)并且通常可能被认为是一个坏主意,但无论如何都值得一提。
如果我理解了您的问题,您希望foo
中的(def bunny {:foo foo :bar bar})
不被粘贴"作为完整副本,而是保留"参考"到(def foo..)
,原来的foo
地图只被序列化一次。
我会考虑的一种技术虽然不一定鼓励(并且只有在耗尽其他选项之后,例如Frank C.暗示的数据结构的重新设置) ),是序列化bunny
的代码而不是结构本身。然后你读回代码字符串和eval
它。只有当bunny的结构没有改变时,或者如果它没有改变,你才可以轻松地构建一个兔子地图的字符串,其中包含作为字符串一部分的相关符号,而不是这些符号的内容。
但更好的想法是序列化你的" raw"数据结构仅,如地图foo
和bar
,然后在读回这些数据后构建您的bunny
- 同时序列化结构但不是兔子的内容。我相信这就是弗兰克的答案。
值得注意的是,如果bunny的结构确实动态变化,并且您能够按照上面的建议创建一串符号,那么这意味着您还可以使用工具来构建如上面2中所示的兔子的表示,这将是更可取的。
由于代码是数据,因此选项1是我们作为lisp程序员可用的灵活性类型的一个示例 - 但这并不意味着没有更好的选择。