【发布时间】:2016-08-02 11:44:40
【问题描述】:
据我了解,当您使用如下表达式创建新列表时,Erlang 不会复制 L1,它只会复制 H。
L2 = [H|L1]
Erlang 是否有针对dict 的持久数据结构(参见Persistent data structure),也就是说,当您在树中添加/删除/修改节点时,只有少数元素被复制(如Clojure)?
【问题讨论】:
据我了解,当您使用如下表达式创建新列表时,Erlang 不会复制 L1,它只会复制 H。
L2 = [H|L1]
Erlang 是否有针对dict 的持久数据结构(参见Persistent data structure),也就是说,当您在树中添加/删除/修改节点时,只有少数元素被复制(如Clojure)?
【问题讨论】:
您在使用[H|T] 构建列表时误解了这种情况。正如您所说,T 没有被复制,但H 也不是。所发生的只是一个新的列表单元被添加到T 前面,并引用H 作为其头部(它的尾部是T)。使用列表时,创建的唯一位是实际的列表单元格,而不是每个单元格中的数据。
使用dict 时也会发生同样的情况。当您在dict 中修改(添加/删除元素)时,只会修改实际的dict 结构,而不会修改dict 中的实际数据。此外,只复制尽可能少的 dict 结构以进行修改也很聪明。
所以,是的,Erlang 有持久的数据结构。在这方面,clojure 就像 Erlang(我们早在它之前就已经存在了)。
【讨论】:
A = SomeTree, B = change(A). 你现在有了树 B 和树 A,其中 B 是新的,A 是旧的。使用 {A,B} 将两棵树放在同一个元组。这是你想知道的吗?
dict、gb_trees 和 array 库以这种方式工作。 lists 库也是如此,尽管它仅适用于列表。这是做事的标准方式,所以原则上所有处理数据结构的库都这样做。
根据我的经验,库模块的数据结构在变大时不会降低性能或内存压力。
对于 dict,它使用动态哈希表作为内部数据结构,并且工作基本上只在完成修改的存储桶上完成。
我还查看了gb_trees 模块,在其中找到了评论:
行为是对数的(应该如此)。
而gb_trees 通常速度很快,所以我很确定不会进行太多复制。
一般来说,如果你用像 Erlang 这样的语言来实现这样的数据结构,你会处理复制问题,所以对于一般的库函数就不用担心了。
我重读了关于持久化数据结构的文章:在这篇文章的意义上,Erlang 的数据结构是完全持久化的,也是融合持久化的。
【讨论】: