從@ fl00r的回答都很好,但我想在一個還原一個以及拋出:
個
可還原對於這種使用情況更好的選擇,因爲
range
用Clojure 1.7被重建爲自還原的,更長久的開始/步/結束值的特殊情況下,它會使用原始的在自我減少期間。
- 使用到傳感器的形式表示,最後的向量可以直接內置,而不是建立一個懶序列,然後把它變成一個載體
- 構建載體時
into
會自動使用瞬態 - 有一個小的開銷(與循環方法相比),但在較大範圍內節省大量費用
- 由於您正在構建混凝土集合(矢量),所以懶惰不會帶來好處,因此熱切的方法更有意義
- 這種方法比任何序列方法的時間和內存效率要高得多。
range
作爲reducible將消耗堆空間(只有幾個當地人)。瞬態矢量是通過填充數組構建的,然後根據需要直接構建持久性矢量節點。通過比較,所有的序列方法都會對迭代器進行盒裝數學計算,構建多個嵌套的緩存序列值,然後將這些值逐個複製到向量中。上面使用的循環方法將使用原始數學,並獲得一些性能優勢(但仍然存在向向量與瞬變添加元素的缺點)。
快速PERF測試(針對不同大小的矢量):
Size | range/vec | iterate/vec | loop/recur | loop/recur' | range/into |
-----|---------------|---------------|---------------|---------------|---------------|
1 | 160.968880 ns | 180.287974 ns | 40.373079 ns | 79.203722 ns | 136.157046 ns |
10 | 378.058753 ns | 851.381372 ns | 342.720391 ns | 200.658997 ns | 253.015756 ns |
100 | 2.486726 µs | 8.034826 µs | 3.464423 µs | 1.471333 µs | 1.760118 µs |
1000 | 23.349414 µs | 88.188242 µs | 37.247193 µs | 16.443044 µs | 17.109882 µs |
逆足試驗是用繞圈快速板凳上的Java 1.8/1的Clojure做。8個
版本進行測試:
- 範圍/ VEC - 第一示例從@ fl00r - 原始數學,1個序列,瞬變
- 迭代/ VEC - 從@ fl00r第二示例 - 盒裝數學,2個序列,瞬變
- 環路/ RECUR - 從@ fl00r 3ND例如 - 原始數學,0的序列,沒有瞬變
- 環路/ RECUR」 - 相同之前,但修改爲使用瞬變 - 原始數學,0序列,瞬變
- 範圍/成 - 在這個答案的上方的例子 - 原始數學,0序列,瞬態
注意的是,過去兩年中也有類似的特徵,但環/復發」大量採用了更多的代碼:
(defn get-range [n] ;; loop/recur'
(loop [m 1
res (transient [])]
(if (> m n)
(persistent! res)
(recur (inc m) (conj! res m)))))
'(range 1(inc number))'或者,得到一個向量'(vec(range ...))' – leetwinski