Clojure butlast 与 drop-last
Clojure butlast vs drop-last
Clojure 中的 butlast
and drop-last
有什么区别?
仅仅是懒惰吗?我应该更喜欢其中之一吗?
是的,惰性以及 drop-last
可以取的事实也取 n
,表示惰性地从末尾丢弃多少个元素。
有一个讨论 here,其中有人认为 butlast
更具可读性并且可能是 Lisp 程序员熟悉的习惯用语,但我通常只选择使用 drop-last
。
此外,如果您需要实现整个集合,butlast
会快得多,如果您查看它们的来源,这是合乎逻辑的:
(def
butlast (fn ^:static butlast [s]
(loop [ret [] s s]
(if (next s)
(recur (conj ret (first s)) (next s))
(seq ret)))))
(defn drop-last
([s] (drop-last 1 s))
([n s] (map (fn [x _] x) s (drop n s))))
所以 drop-last
使用 map
,而 butlast
使用 recur
的简单迭代。这是一个小例子:
user> (time (let [_ (butlast (range 10000000))]))
"Elapsed time: 2052.853726 msecs"
nil
user> (time (let [_ (doall (drop-last (range 10000000)))]))
"Elapsed time: 14072.259077 msecs"
nil
所以我不会盲目地偏爱其中一个。我只在真正需要懒惰的时候才使用drop-last
,否则butlast
.
Clojure 中的 butlast
and drop-last
有什么区别?
仅仅是懒惰吗?我应该更喜欢其中之一吗?
是的,惰性以及 drop-last
可以取的事实也取 n
,表示惰性地从末尾丢弃多少个元素。
有一个讨论 here,其中有人认为 butlast
更具可读性并且可能是 Lisp 程序员熟悉的习惯用语,但我通常只选择使用 drop-last
。
此外,如果您需要实现整个集合,butlast
会快得多,如果您查看它们的来源,这是合乎逻辑的:
(def
butlast (fn ^:static butlast [s]
(loop [ret [] s s]
(if (next s)
(recur (conj ret (first s)) (next s))
(seq ret)))))
(defn drop-last
([s] (drop-last 1 s))
([n s] (map (fn [x _] x) s (drop n s))))
所以 drop-last
使用 map
,而 butlast
使用 recur
的简单迭代。这是一个小例子:
user> (time (let [_ (butlast (range 10000000))]))
"Elapsed time: 2052.853726 msecs"
nil
user> (time (let [_ (doall (drop-last (range 10000000)))]))
"Elapsed time: 14072.259077 msecs"
nil
所以我不会盲目地偏爱其中一个。我只在真正需要懒惰的时候才使用drop-last
,否则butlast
.