我已经知道不可变数据结构在Scala中不能有循环。
但是,如何处理多个父母的子更新?
val child = Child("Tom")
val mother = Parent("Susi", child)
val father = Parent("Chuck", child)
val renamedChild = child.copy(name = "Tommy")
// how to update both references?
我对拉链的看法并不多,但我认为它们只适用于简单的树而不是DAG的权利?
答案 0 :(得分:1)
在不可变/持久数据结构中,您具有结构共享,因此在执行更新时,必须更新整体结构的一部分。对于像树一样的层次结构(如您的示例所示),这意味着您必须从上到下更新从根到您孩子的路径。这反过来要求您了解您的父母。
如果mother
和father
是"自由浮动"如果没有root,你也必须更新它们:
val mother1 = mother.copy(child = renamedChild)
val father1 = father.copy(child = renamedChild)
如果您有嵌套的数据结构,并且希望避免手动记账(这很容易导致错误),您可以使用Lenses等方法。
如果你的结构是一个有向无环图,找到一个不可变的实现可能是一个挑战(我不知道一个持久的DAG结构 - 它可能是可行的,将DAG分解成一个集合树木,但我没有遇到任何这样的实施。)
当然,你总是可以拥有一个天真(表现不佳)的版本。
// set of vertices and map that points from children to parents!
type Graph[A] = (Set[A], Map[A, Set[A]])
def update[A](graph: Graph[A], before: A, now: A): Graph[A] = {
val (vertices, edges) = graph
val newV = vertices - before + now
val parents = edges.getOrElse(before, Set.empty)
val newE = if (parents.isEmpty) edges else edges - before + (now -> parents)
(newV, newE)
}
val g1 = Set("Tom", "Susi", "Chuck") -> Map("Tom" -> Set("Susi", "Chuck"))
val g2 = update(g1, "Tom", "Tommy")