Clojure 中的指针循环
我正在编写一个解析 XML 的 clojure 程序。作为其中的一部分,我希望基于 clojure.xml/parse 函数在 XML 文档中创建节点树。但是我希望树是双向的 - 也就是说,每个节点都有一个子节点列表和一个指向其父节点的指针。只有一个问题:所有数据都是不可变的,因此我无法在不更改子项的情况下“添加”指向父项的指针,从而使父项的指针毫无用处。
我找到了这个答案: 如何在 Clojure 中创建循环(且不可变)数据结构而不需要额外的间接?
建议的解决方案似乎是创建一个单独的索引映射,它引用内部的对象。对于一个更糟糕的解决方案来说,这似乎是一项巨大的工作量。我对树在构造过程中可变没有问题,但我不知道如何做到这一点。 clojure 中真的没有办法获取循环指针吗?
谢谢!
I'm writing a clojure program which parses XML. As a part of this, I wish to create a tree of the nodes in the XML document, based on the clojure.xml/parse function. However I'd like the tree to be bi-directional - that is, each node has a list of children, and a pointer to its parent. There is only one problem: all data is immutable, and so I can't 'add' a pointer to the parent without changing the child, thus making the parent's pointer useless.
I've found this answer: How can one create cyclic (and immutable) data structures in Clojure without extra indirection?
The solution suggested there seems to be creating a separate index map, which refers to the objects inside. This seems like a huge amount of work for a much worse solution. I'd have no problem for the tree to be mutable during construction, however I can't figure out how can it be done. Is there really no way to get a cyclic pointer in clojure?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
从逻辑上讲,不可能使纯不可变结构成为循环结构,因为通过添加父指针或子指针将会改变结构。
有一个可行的技巧,但我不确定我是否会推荐它:您可以将原子放入 Clojure 数据结构中,然后更改它们以建立必要的链接。例如,
这在各个方面都是令人讨厌的:
因此,如果您真的想这样做,这是可能的……尽管我个人认为,从长远来看,如果您使文档表示适当地不可变,您的情况仍然会好得多。如果您想导航结构,您也许可以在文档中使用更像 XPath 样式位置的内容。
It's logically impossible to make pure immutable structures cyclic, since by adding a parent or child pointer you would be mutating the structure.
There is a hack that works though I'm not sure I'd recommend it: you can put atoms inside Clojure data structures and then mutate these to make the necessary links. e.g.
This is nasty in all sorts of ways:
So, it is possible if you really want to do it......... though I personally think you are still much better off in the long run if you make your document representation properly immutable. You could perhaps use something more like XPath style locations in the document if you want to navigate the structure.
您是否考虑过使用拉链?
拉链的设计目的是为了有效地处理树状结构。它包括基本操作,例如查看 子项 和在节点的 父 节点,同时还允许<一href="http://clojure.github.com/clojure/clojure.zip-api.html#clojure.zip/next" rel="nofollow">轻松迭代结构。
拉链是相当通用的,并且包含的功能已经允许从 XML 创建它们。 上的示例其他库页面提供了如何使用它们的良好初步图片。
对于 XML 拉链,您需要使用它
来创建初始结构。完成后,只需调用
root
即可获取最终结构。Have you considered using zippers?
Zippers are designed for allowing for working with tree like structures effectively. It includes basic operations like looking at children and at the parent of a node while also allowing easily iterating through the structure.
Zippers are fairly generic and included functions already allow creating them from XML. An example on the Other Libraries page offers a good initial picture of how to work with them.
For an XML zipper, you'll want to use
to create the initial structure. When you're done, just call
root
to get the end structure.像这样的事情是可行的:
使协议不成为公共 API 的一部分,并且在构建后永远不要触及可变字段,这样你基本上就拥有了一棵不可变的树。然而,在构建后修改所述树将很困难。 YMMV。
Something like this could work:
Make the protocol not part of the public API and never touch the mutable field after construction and you basically have an immutable tree. However modifying said tree after construction will be hard. YMMV.