在读《clojure编程》,其中讲到在易变集合上使用更新操作,那么这个集合就不可再使用了,即便是读取操作也不行。但是为什么执行下面的代码,依然能输出结果呢?
(def x (tranisent #{}))
(reduce conj! x (range 10))
(count x)
(x 2)
最后依然能输出10和2,这是为什么呢?conj!不是已经对易变的x进行了修改操作吗?
在读《clojure编程》,其中讲到在易变集合上使用更新操作,那么这个集合就不可再使用了,即便是读取操作也不行。但是为什么执行下面的代码,依然能输出结果呢?
(def x (tranisent #{}))
(reduce conj! x (range 10))
(count x)
(x 2)
最后依然能输出10和2,这是为什么呢?conj!不是已经对易变的x进行了修改操作吗?
因为不懂,查阅了下。书中举例如下:
(def x (transient []))
;= #'user/x
(def y (conj! x 1))
;= #'user/y
(count y)
;= 1
(count x)
;= 1
x定义为transient vector,执行更新操作后,可以执行读取操作。书中的原话“ After modification, any reference to an old revision of a transient collection cannot be relied upon; it may be valid, it may be the new value, or it may be garbage”。
查阅官网文档,transient数据结构适合大量元素更新。因为不用复制数据与数据结构间的转换是O(1)操作,所以快。
defn vrange [n]
(loop [i 0 v []]
(if (< i n)
(recur (inc i) (conj v i))
v)))
(defn vrange2 [n]
(loop [i 0 v (transient [])]
(if (< i n)
(recur (inc i) (conj! v i))
(persistent! v))))
;; benchmarked (Java 1.7, Clojure 1.8)
(time (def v (vrange 1000000))) ;; "Elapsed time: 364.37862 msecs"
(time (def v2 (vrange2 1000000))) ;; "Elapsed time: 239.557479 msecs"
备注:1.测试结果官方提供数据差异大,可能是机器不同。2.你提供的代码不能执行,transient拼写错误。