Is there a simpler way to remove the last element of a list than this?
(setq list (reverse (cdr (reverse list))))
Emacs Stack Exchange is a question and answer site for those using, extending or developing Emacs. It only takes a minute to sign up.Sign up to join this community
Yes there is:
(setq list (butlast list))
That is a function from
subr.el. (Loaded by default. No need to load anything.)
You can also cut a tail with
N elements by
(setq list (butlast list N))
A word about phils' comment:
If it's safe to modify the original list structure, then
nbutlastwill be slightly more efficient (n.b. you still need to assign the result back to the variable).
The comment is right and useful but it has to be considered very cautious.
For an exmple the application of
nbutlast is safe if the following three conditions are fulfilled:
Be aware that
nbutlast modifies the argument
list in the calls of the following functions!
(defun queue (el list) "Prepend el and remove last element." (nbutlast (cons el list))) (defun foo (head list) "Prepend head and remove last element." (nbutlast (append head list))) (setq list (list 2 3 4)) (queue 1 list) list ;; -> (2 3) (foo '(1) list) list ;; -> (2)
The sequences library bundled with Emacs makes this easily generalized. Here I demonstrate a possible implementation in an IELM buffer.
ELISP> (defun seq-butlast-elt (seq) "Return a copy of SEQ without its final element." (seq-take seq (1- (seq-length seq)))) seq-butlast-elt ELISP> (seq-butlast-elt '(1 2 3)) (1 2) ELISP> (seq-butlast-elt '(1)) nil ELISP> (seq-butlast-elt '()) nil ELISP> (seq-butlast-elt ["oak" "cherry" "apple"]) ["oak" "cherry"] ELISP> (seq-butlast-elt ["apple"])  ELISP> (seq-butlast-elt )  ELISP> (seq-butlast-elt "dogs") "dog" ELISP> (seq-butlast-elt "d") "" ELISP> (seq-butlast-elt "") ""
This might not be the fastest possible implementation.