Scala DAG更新了几位家长

时间:2015-01-06 20:50:33

标签: scala data-structures immutability

我已经知道不可变数据结构在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的权利?

1 个答案:

答案 0 :(得分:1)

在不可变/持久数据结构中,您具有结构共享,因此在执行更新时,必须更新整体结构的一部分。对于像树一样的层次结构(如您的示例所示),这意味着您必须从上到下更新从根到您孩子的路径。这反过来要求您了解您的父母。

如果motherfather是"自由浮动"如果没有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")