As Rainer Joswig said, you should use the generic built-in function lisp butlast
.
But, if you still want to see what an efficient recursive version looks like:
(defun butlast2 (list) (labels ((butlast2-worker (list result) (if (null list) (nreverse result) (let ((element (first list)) (rest (rest list))) (if (null rest) (nreverse result) (butlast2-worker rest (cons element result))))))) (butlast2-worker list ())))
As long as your lisp implementation supports tail call optimization, it will be converted to a loop. The trick is that whenever butlast2-worker
is called, its result will be returned directly, which means you do not need to track the arguments / internal variables from previous function calls. The latter means that you do not need to populate the call stack, as usual, for a recursive function.
Looking at the definition of Rainer Joslig, you can see a huge difference in size. Here is the power of the loop
and learn to use it wisely whenever you can (or better: use iterate
http://common-lisp.net/project/iterate/ ).
source share