如何在Clojure数据结构中"标记"一个节点?

Joe*_*Joe 6 clojure clojurescript

我有

  • 一个Clojure数据结构,我们称之为dom一个向量树和无限深度的地图;
  • 在其中的一个特定节点,我们称之为focus节点,称为树的路径:一系列密钥,例如您可以呈现的 get-in.

我将在一个函数中决定聚焦节点,并且我想以某种方式表示聚焦节点的选择,其方式可以以不违反不变性的方式传递给另一个函数,并且不与Clojure的持久数据结构冲突.

当我遍历树时,我想以focus不同的方式处理节点:例如,如果我打印树,我可能想要以粗体打印focus节点.

如果我使用的是C或Java,我可以保存一个指向focus节点的指针/引用,当我遍历树时,我可以将其与当前节点进行比较.我不认为这是在Clojure中做到这一点的正确方法:它感觉很hacky,而且我确信有一些方法可以利用Clojure的持久数据结构.

该解决方案必须适用于Clojure和ClojureScript.

我能想到的选择是:

  1. 存储参考并检查.
  2. 将标记附加到相关节点.
  3. 同时递归到树中并沿着指向标记节点的路径.

    • 正如我所解释的,选项(1)没有吸引力.
    • 选项(2)似乎是最好的,并且给定持久数据结构是无痛的.
    • 选项(3)类似于选项(2),除了它结合了标记和遍历步骤.

我确定这是一个常见的问题.它有标准的解决方案吗?

Thu*_*ail 2

我建议您重新考虑@MerceloMorales 的建议:使用元数据。您的节点对象将具有一个不影响其正常功能的偶然属性。这就是元数据的设计目的。它可以在 ClojureScript 中运行。我能想到的使用元数据的唯一原因是节点值不是 Clojure 对象,而是一个数字。

《Clojure Cookbook》中,2.22。Luke Vanderhart为一个键保留多个值,使用元数据来解决类似的问题:将需要解释为集合而不是单个值的条目标记。

另一种方法可能是使用拉链来遍历/修改节点树。拉链是根据 - 你已经猜到了 - 元数据来实现的。

我同意您对元数据的疑虑:将任何旧的东西附加到您的数据上都会让人感到恶心 - 就像用寄生虫感染它一样。然而,它与对象的其他部分一样是不可变的。


使用拉链的建议很幼稚:标准的 clojure 拉链是为顺序容器的层次结构设计的,而不是为关联容器设计的。