Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure butlast vs drop-last

What is the difference between butlast and drop-last in Clojure ?

Is it only the laziness ? Should I should prefer one over the other ?

like image 649
nha Avatar asked Apr 20 '16 05:04

nha


2 Answers

also, if you need to realize the whole collection, butlast is dramatically faster, which is logical if you look at their source:

(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))))

so drop-last uses map, while butlast uses simple iteration with recur. Here is a little example:

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

so i wouldn't blindly prefer one over another. I use drop-last only when i really need laziness, otherwise butlast.

like image 97
leetwinski Avatar answered Sep 19 '22 03:09

leetwinski


Yes, laziness as well as the fact that drop-last can take also take n, indicating how many elements to drop from the end lazily.

There's a discussion here where someone is making the case that butlast is more readable and maybe a familiar idiom for Lisp programmers, but I generally just opt to use drop-last.

like image 28
lsankar4033 Avatar answered Sep 23 '22 03:09

lsankar4033