Clojure China

初学者,关于易变集合的一个疑惑

clojure
#1

在读《clojure编程》,其中讲到在易变集合上使用更新操作,那么这个集合就不可再使用了,即便是读取操作也不行。但是为什么执行下面的代码,依然能输出结果呢?

(def x (tranisent #{}))
(reduce conj! x (range 10))
(count x)
(x 2)

最后依然能输出10和2,这是为什么呢?conj!不是已经对易变的x进行了修改操作吗?

#2

因为不懂,查阅了下。书中举例如下:

(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拼写错误。

参考:http://clojure.org/reference/transients#_example

1赞
#3

x修改为10个数字的集合,所以count结果10,集合中包括2。完全没问题啊。

这个是可变集合的意思吧,为了效率而设计的吧。

clojure默认是不变数据。