Clojure 为什么‘坚持!’仅从瞬态中获取前八项?
我正在学习Clojure,在此过程中,我遇到了O'Reilly的书《Clojure编程》中的这个例子: 它给出了结果Clojure 为什么‘坚持!’仅从瞬态中获取前八项?,clojure,persistent,transient,Clojure,Persistent,Transient,我正在学习Clojure,在此过程中,我遇到了O'Reilly的书《Clojure编程》中的这个例子: 它给出了结果{0,10,20,30,40,50,60,70} 此外: 给出相同的结果:{0,10,20,30,40,50,60,70} 为什么只有前八项才能进入持久性收藏?多么迷人 首先,这看起来像是惰性seq的分块问题-为了测试,我稍微修改了您的示例: (let [tm (transient {})] (doseq [x (range 100)] (println "assoc!
{0,10,20,30,40,50,60,70}
此外:
给出相同的结果:{0,10,20,30,40,50,60,70}
为什么只有前八项才能进入持久性收藏?多么迷人
首先,这看起来像是惰性seq的分块问题-为了测试,我稍微修改了您的示例:
(let [tm (transient {})]
(doseq [x (range 100)]
(println "assoc! " x)
(assoc! tm x 0))
(persistent! tm))
令我惊讶的是,这确实打印了100行文本,但正如您所观察到的,最终的集合只包含8项。我不能确切地说为什么,除了它似乎是实现瞬变的一个工件之外
我能说的是,这不是习惯用语clojure。对于按照规定构建地图的任务,我将采用以下方法:
(reduce (fn [m n] (assoc m n 0)) {} (range 100))
如果这实际上是一个性能明智的问题,我可能会考虑<代码>循环< /代码>构造中的瞬变:
(loop [m (transient {})
ns (range 100)]
(if-let [n (first ns)]
(recur (assoc! m n 0) (rest ns))
(persistent! m))
您所面临的关键问题是,虽然瞬态是可变的,但它们旨在以某种功能性的方式使用。如果将瞬态映射视为持久映射-也就是说,保持assoc代码>而不是假设一个引用总是有效的-你会没事的。多么迷人
首先,这看起来像是惰性seq的分块问题-为了测试,我稍微修改了您的示例:
(let [tm (transient {})]
(doseq [x (range 100)]
(println "assoc! " x)
(assoc! tm x 0))
(persistent! tm))
令我惊讶的是,这确实打印了100行文本,但正如您所观察到的,最终的集合只包含8项。我不能确切地说为什么,除了它似乎是实现瞬变的一个工件之外
我能说的是,这不是习惯用语clojure。对于按照规定构建地图的任务,我将采用以下方法:
(reduce (fn [m n] (assoc m n 0)) {} (range 100))
如果这实际上是一个性能明智的问题,我可能会考虑<代码>循环< /代码>构造中的瞬变:
(loop [m (transient {})
ns (range 100)]
(if-let [n (first ns)]
(recur (assoc! m n 0) (rest ns))
(persistent! m))
您所面临的关键问题是,虽然瞬态是可变的,但它们旨在以某种功能性的方式使用。如果将瞬态映射视为持久映射-也就是说,保持assoc代码>而不是假设一个引用总是有效的-你会没事的。为什么只有前8项
(type {})
;=> clojure.lang.PersistentArrayMap
(type {0 0, 1 0, 2 0, 3 0, 4 0, 5 0, 6, 0})
;=> clojure.lang.PersistentArrayMap
(type {0 0, 1 0, 2 0, 3 0, 4 0, 5 0, 6, 0, 7 0})
;=> clojure.lang.PersistentArrayMap
(type {0 0, 1 0, 2 0, 3 0, 4 0, 5 0, 6, 0, 7 0, 8 0})
;=> clojure.lang.PersistentHashMap
因为贴图的表示在8对和更少对之间更改为8对或更多对。因为你是在“原地痛击”原作,所以你从来没有捕捉到表达的变化
处理瞬态时,必须始终捕获并使用返回值 为什么只有前8项
(type {})
;=> clojure.lang.PersistentArrayMap
(type {0 0, 1 0, 2 0, 3 0, 4 0, 5 0, 6, 0})
;=> clojure.lang.PersistentArrayMap
(type {0 0, 1 0, 2 0, 3 0, 4 0, 5 0, 6, 0, 7 0})
;=> clojure.lang.PersistentArrayMap
(type {0 0, 1 0, 2 0, 3 0, 4 0, 5 0, 6, 0, 7 0, 8 0})
;=> clojure.lang.PersistentHashMap
因为贴图的表示在8对和更少对之间更改为8对或更多对。因为你是在“原地痛击”原作,所以你从来没有捕捉到表达的变化
处理瞬态时,必须始终捕获并使用返回值 可能的重复我不认为这是一个重复的问题,尽管两个问题的答案是相同的。可能的重复我不认为这是一个重复的问题,尽管两个问题的答案是相同的。关键部分来自于:“瞬变不意味着在适当的地方被击打”。还有更多关于为什么会发生这种情况的描述。简短的说法是,数据表示可能在某些点发生变化。关键的一点来自于:“瞬变并不意味着要在适当的位置受到冲击”。还有更多关于为什么会发生这种情况的描述。简短的版本是,数据表示可能会在某些点发生变化。Shepmaster的评论中有一些非常解释性的链接,如下所示:此外,Ben的评论中有一个正确的陈述。Shepmaster的评论中有一些非常解释性的链接,如下所示:此外,Ben的评论中有一个正确的陈述。