帮助我理解Clojure如何处理不变性和运行时间之间的冲突

帮助我理解Clojure如何处理不变性和运行时间之间的冲突,clojure,immutability,hashset,performance,Clojure,Immutability,Hashset,Performance,Clojure确实激起了我的兴趣,我开始学习关于它的教程: 考虑“集合”中提到的这两行: 我的第一个想法是,第二次手术需要一定的时间才能完成;否则,函数式语言可能比面向对象的语言没有什么好处。人们可以很容易地想象,我们需要从[几乎]空的集合开始,然后填充它,并在继续的过程中缩小它。因此,我们可以将新结果重新分配给自身,而不是将其分配给更多的傀儡 现在,由于函数式语言的神奇前景,副作用已经不必担心了。因此,集合stooges和more stooges不应该相互重叠。因此,要么创建更多的stoog

Clojure确实激起了我的兴趣,我开始学习关于它的教程:

考虑“集合”中提到的这两行:

我的第一个想法是,第二次手术需要一定的时间才能完成;否则,函数式语言可能比面向对象的语言没有什么好处。人们可以很容易地想象,我们需要从[几乎]空的集合开始,然后填充它,并在继续的过程中缩小它。因此,我们可以将新结果重新分配给自身,而不是将其分配给更多的傀儡

现在,由于函数式语言的神奇前景,副作用已经不必担心了。因此,集合
stooges
more stooges
不应该相互重叠。因此,要么创建更多的stooges是一个线性操作,要么它们共享一个公共缓冲区(如Java的
StringBuffer
),这似乎是一个非常糟糕的想法,并且与不变性相冲突(随后
stooges
可以逐个删除元素)

我可能在这里重新发明了一个轮子。在
clojure
中,当您从最大数量的元素开始,然后一次删除一个元素,直到出现空集,而不是从空集开始,一次增加一个元素时,
哈希集的性能似乎会更好

上面的例子可能看起来不太实用,或者没有解决办法,但是像Java/C#/Python/等面向对象语言在快速增长或收缩一组元素的同时,一次增长或收缩一个或几个元素是没有问题的

一种保证(或仅仅承诺?)不变性的[函数式]语言将无法以如此快的速度增长集合。有没有另外一个成语可以用来帮助人们避免这样做

对于熟悉
Python
的人,我要提到集合理解与等效循环方法。两者的运行时间略有不同,但这与
C
Python
、解释器的相对速度有关,而不是基于复杂性。我看到的问题是,集合理解通常是一种更好的方法,但并不总是最好的方法,因为可读性可能会受到很大影响


如果问题不清楚,请告诉我。

Clojure的数据结构是持久的,这意味着它们是不可变的,但使用结构共享来支持有效的“修改”。请参阅Clojure文档中关于的部分,以获得更全面的解释。它特别指出

具体来说,这意味着不能使用完整副本创建新版本,因为这需要线性时间。不可避免地,持久性集合是使用链接数据结构实现的,因此新版本可以与以前的版本共享结构


,以及其中的一些,很好地概述了持久数据结构的实现。

核心不可变数据结构也是语言中最吸引我的部分之一。他们对回答这个问题很有帮助,Rich在这段视频中做得非常出色:

核心数据结构:

  • 它们实际上是完全不变的
  • 旧副本也是不可变的
  • 旧拷贝的性能不会降低

  • 访问是恒定的(实际上是一个与trie不同的“trei”,还是仅仅是一个输入错误?它的trei(发音为try)我只是有点键盘问题:)来自维基百科文章:trie一词来自“检索”。根据词源,发明家爱德华·弗雷德金(Edward Fredkin)将其发音为“树”。然而,其他作家却把它读作“尝试”。@迈克·邓拉维,你是一名国际象棋棋手,卡布奇诺·德林金·伊利主义者。阿威·舒克(脸红):-)只是抬头看了看“伊利主义者”。这并不意味着一个文盲和以此为荣的人。“回肠炎”“这是一种肠道疾病。我相信你也不是那个意思:)删除有多复杂?假设我有10个不同的集合或字典,它们是以增量方式创建的。然后我从第一个set/dict(只包含一个元素的set/dict)中删除所有10个节点共有的节点。clojure将做什么以及需要多长时间?不管集合/字典是增量构建还是一次性构建。删除和添加一样有效——它实际上是一个固定时间的操作。
    (def stooges (hash-set "Moe" "Larry" "Curly")) ; not sorted
    (def more-stooges (conj stooges "Shemp")) ; -> #{"Moe" "Larry" "Curly" "Shemp"}