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.