Add the &optional n for BUTLAST
[jscl.git] / src / list.lisp
index 9cb8e45..7a06dd7 100644 (file)
     (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)