1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2025-01-07 15:21:46 +00:00

Speed up butlast

* lisp/subr.el (butlast): Don't duplicate the removed part.
* test/lisp/subr-tests.el (subr-tests--butlast-ref, subr-butlast):
Add test.
This commit is contained in:
Mattias Engdegård 2022-07-19 11:59:37 +02:00
parent 4b807380cf
commit c80adde1d9
2 changed files with 24 additions and 4 deletions

View File

@ -707,11 +707,14 @@ If N is bigger than the length of LIST, return LIST."
(defun butlast (list &optional n)
"Return a copy of LIST with the last N elements removed.
If N is omitted or nil, the last element is removed from the
copy."
If N is omitted or nil, return a copy of LIST without its last element.
If N is zero or negative, return LIST."
(declare (side-effect-free t))
(if (and n (<= n 0)) list
(nbutlast (copy-sequence list) n)))
(unless n
(setq n 1))
(if (<= n 0)
list
(take (- (length list) n) list)))
(defun nbutlast (list &optional n)
"Modify LIST to remove the last N elements.

View File

@ -1090,5 +1090,22 @@ final or penultimate step during initialization."))
(should-not (plistp '(1 2 3)))
(should-not (plistp '(1 2 3 . 4))))
(defun subr-tests--butlast-ref (list &optional n)
"Reference implementation of `butlast'."
(let ((m (or n 1))
(len (length list)))
(let ((r nil))
(while (and list (> len m))
(push (car list) r)
(setq list (cdr list))
(setq len (1- len)))
(nreverse r))))
(ert-deftest subr-butlast ()
(dolist (l '(nil '(a) '(a b) '(a b c) '(a b c d)))
(dolist (n (cons nil (number-sequence -2 6)))
(should (equal (butlast l n)
(subr-tests--butlast-ref l n))))))
(provide 'subr-tests)
;;; subr-tests.el ends here