(setq x (cdr x)))
x)
-(defun butlast (x)
- (and (consp (cdr x))
- (cons (car x) (butlast (cdr x)))))
-
-(defun member (x list &key key (test #'eql testp) (test-not #'eql test-not-p))
+(defun butlast (x &optional (n 1))
+ "Returns x, less the n last elements in the list."
+ (cond
+ ;; trivial optimizations
+ ((not x) x)
+ ((zerop n) x)
+
+ ;; Base case
+ ((= n 1)
+ (and (consp (cdr x))
+ (cons (car x)
+ (butlast (cdr x) n))))
+ ;; O(n * (length x)) butlast for n > 1.
+ (t
+ (let ((temp x))
+ (do
+ ((iter 0))
+ ;; quit when we reach the top or we ran out
+ ((or (= iter n)
+ (not temp)))
+ (setf temp (butlast temp 1))
+ (incf iter))
+ temp))))
+
+(defun member (x list &key key (test #'eql testp) (test-not #'eql test-not-p))
(while list
(when (satisfies-test-p x (car list) :key key :test test :testp testp
:test-not test-not :test-not-p test-not-p)