pointers - clojure中的指针循环

标签 pointers data-structures clojure immutability

我正在编写一个解析 XML 的 clojure 程序。作为其中的一部分,我希望基于 clojure.xml/parse 函数在 XML 文档中创建节点树。但是我希望树是双向的——也就是说,每个节点都有一个子节点列表和一个指向其父节点的指针。只有一个问题:所有数据都是不可变的,因此我无法在不更改子项的情况下“添加”指向父项的指针,从而使父项的指针无用。

我找到了这个答案:How can one create cyclic (and immutable) data structures in Clojure without extra indirection?

解决方案表明似乎正在创建一个单独的索引映射,它指的是内部的对象。对于更糟糕的解决方案来说,这似乎是一项巨大的工作。在构造过程中,树是可变的,我没有问题,但是我不知道如何做到这一点。真的没有办法在clojure中获得循环指针吗?

谢谢!

最佳答案

使纯不可变结构循环在逻辑上是不可能的,因为通过添加父或子指针,您将改变结构。

虽然我不确定我是否会推荐它,但有一个 hack 可行:您可以将原子放入 Clojure 数据结构中,然后对它们进行变异以建立必要的链接。例如

(def parent {:id 1 :children (atom nil) :parent (atom nil)})

(def child  {:id 2 :children (atom nil) :parent (atom nil)}) 

(swap! (:children parent) conj child)
(reset! (:parent child) parent)

;; test it works
(:id @(:parent child))
=> 1

这在各方面都令人讨厌:
  • 如果您尝试打印其中之一,它将导致您的 REPL 堆栈溢出,因为 REPL 不期望循环数据结构。
  • 它是可变的,因此您将失去不可变数据结构的所有可维护性和并发性优势(这是 Clojure 最好的事情之一!)
  • 如果要复制节点(例如构建新的 XML 文档),则需要获取节点的完整副本,因为它不再是不可变的值。
  • 当您浏览结构时,取消引用所有原子可能会变得困惑。
  • 您会混淆习惯使用惯用 Clojure 的人。

  • 所以,如果你真的想这样做是有可能的......不过我个人认为,如果你让你的文档表示正确地不可变,从长远来看你仍然会好得多。如果您想导航结构,您也许可以在文档中使用更像 XPath 样式位置的内容。

    关于pointers - clojure中的指针循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9275456/

    相关文章:

    c - 是否有充分的理由不在一个节点中包含多个节点指针以在多个数据结构中使用?

    pointers - 如何在go中定义一个指针,然后将这个指针传递给一个func来改变它的值?

    c - 将 double as (void *) 传递给函数

    python - 有向无环图中的所有唯一路径,以随机顺序,通过 Python 生成器?

    arrays - 为什么在有界队列中使用数组作为数据结构是个坏主意?

    java - 链表移除

    c++ - C++中的const变量和const指针是如何被编译器和操作系统对待的

    clojure - var 或 ref/atom/agent 用于常量值?

    clojure - 带括号的灯 table paredit环绕

    java - 在 Ubuntu 上将 Maven 项目导入到 Eclipse Luna 时出错