【发布时间】:2010-09-09 22:10:22
【问题描述】:
Clojure 真的激起了我的兴趣,我开始阅读它的教程: http://java.ociweb.com/mark/clojure/article.html
考虑一下“Set”下提到的这两行:
(def stooges (hash-set "Moe" "Larry" "Curly")) ; not sorted
(def more-stooges (conj stooges "Shemp")) ; -> #{"Moe" "Larry" "Curly" "Shemp"}
我的第一个想法是第二次操作应该需要恒定的时间才能完成;否则,函数式语言可能比面向对象的语言没有什么好处。可以很容易地想象需要从 [几乎] 空集开始,然后在我们进行的过程中填充和缩小它。因此,我们可以将新结果重新分配给自己,而不是将新结果分配给更多人。
现在,由于函数式语言的奇妙承诺,副作用不再值得关注。所以,集合stooges 和more-stooges 永远不能相互叠加。因此,more-stooges 的创建要么是线性操作,要么它们共享一个公共缓冲区(如 Java 的 StringBuffer),这似乎是一个非常糟糕的主意并且与不变性相冲突(随后 stooges 可以删除一个元素 -一个)。
我可能在这里重新发明了一个轮子。似乎hash-set 在clojure 中的性能更高,当您从最大数量的元素开始然后一次删除它们直到空集,而不是从空集开始并一次增长一个.
上面的例子可能看起来不太实用,或者有变通方法,但是像 Java/C#/Python/等面向对象的语言。一次增加或缩小一个或几个元素,同时速度也很快。
保证(或只是承诺?)不变性的[功能]语言将无法快速增长集合。是否有另一种可以使用的成语以某种方式帮助避免这样做?
对于熟悉Python 的人,我会提到集合理解与等效循环方法。两者的运行时间略有不同,但这与C、Python、解释器的相对速度有关,而不是源于复杂性。我看到的问题是集合理解通常是更好的方法,但并不总是最好的方法,因为可读性可能会受到很大影响。
如果问题不清楚,请告诉我。
【问题讨论】:
-
@Mike Dunlavey,你是一个国际象棋玩家,Capuchino-drinkin ilitism。
-
Awe shucks (blush) :-) 刚查了“ilitist”。这并不意味着一个文盲并以此为荣的人。 “回肠炎”是一种肠道疾病。我敢肯定你也不是那个意思:)
标签: clojure immutability hashset performance