在談話"Bootstrapping Clojure at Groupon" by Tyler Jennings,從25:14到28:24,他討論了separate
功能的兩種實現方式,都採用瞬變:這是瞬變的正確用法嗎?
(defn separate-fast-recur [pred coll]
(loop [true-elements (transient [])
false-elements (transient [])
my-coll coll]
(if (not (empty? my-coll))
(let [curr (first my-coll)
tail (rest my-coll)]
(if (pred curr)
(recur (conj! true-elements curr) false-elements tail)
(recur true-elements (conj! false-elements curr) tail)))
[(persistent! true-elements) (persistent! false-elements)])))
(defn separate-fast-doseq [pred coll]
(let [true-elements (transient [])
false-elements (transient [])]
(doseq [curr coll]
(if (pred curr)
(conj! true-elements curr)
(conj! false-elements curr)))
[(persistent! true-elements) (persistent! false-elements)]))
(這些都是逐字複製,包括在最後unidiomatic縮進)
他指出,在他使用的基準測試中,上面的第一個函數花了1.1秒,而上面的第二個函數花了0.8秒,注意到第二個函數因此優於第一個函數。然而,根據Clojure documentation on transients:
特別要注意,暫態不是設計在現場。您必須在下次調用中捕獲並使用返回值。
因此,在我看來,這個separate-fast-doseq
函數是不正確的。但考慮到談話其餘部分的性質,我很難相信這是不正確的。
這是separate-fast-doseq
功能瞬變的正確使用?爲什麼或者爲什麼不?(如果不是,那是什麼突破的例子嗎?)
聽起來好像是:不這樣做,它只是碰巧工作,能夠隨時休息。 「但它在我的機器上工作」,從未走得太遠。 –