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!

我正在学习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! " 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的评论中有一个正确的陈述。