每本教科书都说Clojure数据结构是不可变的和持久的。他们用不同的长度来解释这个概念,但到目前为止,我没有弄清楚不变性和持久性之间的区别。是否存在持久但可变的实体?或不可变但不持久?
答案 0 :(得分:5)
不可变意味着不能更改该值,并且持久性意味着如果该值已存在于程序中,则复制该值的路径。 Clojure将其作为其结构共享实现的一部分。如果数据不存在,则创建它。如果数据存在,则新数据将基于旧版本的数据构建,而不会更改或删除它。
原子是持久但安全可变的。
user> (def +a+ (atom 0))
#'user/+a+
user> @+a+
0
user> (swap! +a+ inc)
1
user> @+a+
1
瞬变是可变的,但应该在突变后持久化
user> (def t (transient []))
#'user/t
user> (conj! t 1)
#<TransientVector clojure.lang.PersistentVector$TransientVector@658ee462>
user> (persistent! t)
[1]
了解Clojure的持久向量,pt。 1 =&gt; http://hypirion.com/musings/understanding-persistent-vector-pt-1
持久性数据结构=&gt; https://en.wikipedia.org/wiki/Persistent_data_structure
持久性数据结构和托管引用=&gt; http://www.infoq.com/presentations/Value-Identity-State-Rich-Hickey
答案 1 :(得分:4)
纯功能数据结构引用了一篇文章[1],其中似乎包含了 persistent 一词的原始定义:
普通数据结构是 ephemeral ,因为对结构进行更改会破坏旧版本,只留下新版本。 ...如果数据结构支持访问多个版本,我们将其称为 persistent 。如果可以访问所有版本但只能修改最新版本,则结构部分持久,如果每个版本都可以被访问和修改,则完全持久。
[1] James R. Driscoll,Neil Sarnak,Daniel D. Sleator和Robert E. Tarjan。使数据结构持久化。 计算机与系统科学期刊,38(1):86-124,1989年2月。
答案 2 :(得分:1)
Immutable意味着持久性,但持久性并不意味着不可变。所以你可以拥有持久但不可变的东西。
可变且持久的数据结构的一个例子是Java的CopyOnWriteArrayList
。
持久性不意味着共享结构,也没有任何关于性能的说法。当然,共享结构和良好性能都是非常理想的,并且都是由Clojure的持久数据结构提供的。但是很有可能创建一些没有结构共享和糟糕性能的东西(参见CopyOnWriteArrayList
,例如;-))但仍然存在。
答案 3 :(得分:-1)
基本上不可变的==不能改变,而且持久==不可变,具有共享结构。
如果我的语言无法更改数组,那么数组是不可变的。要“更改”数组,我必须创建一个新数组并将每个元素(除了要更改的元素除外)复制到新数组中。这使得任何更新O(n),其中n是数组中元素的数量。对于大n来说,这显然效率低下。
另一方面,如果我使用持久数据结构而不是数组,那么每次数据结构被“更改”时,不是复制每个元素,新版本与旧版本共享大部分相同的结构。
细节取决于结构,但通常通常会涉及一棵树。如果树是平衡的,则替换元素意味着沿着从根到包含元素的叶子的路径创建节点的新副本。其余节点与原始版本共享。该路径的长度为O(n log(n))。由于节点大小为O(1),因此整个操作需要O(n log(n))时间和额外空间。
请注意,并非所有持久性结构都能有效地支持相同的操作。例如,在Clojure中,列表是单链表。您可以有效地添加和删除前面的元素,但这是关于它的。另一方面,向量允许您有效地获取任何元素并在后面添加/删除元素。