X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcode%2Flist.lisp;h=a48af261437bfb0d53ce4361de1937a4de024055;hb=05d9e55946615d14fa26d276b29072931f9dc5b5;hp=225f1bb61dadc74df63bbc54406bab867d74600f;hpb=8e500c66a52b58fd8dab4b098f76e36734d8fdbd;p=sbcl.git diff --git a/src/code/list.lisp b/src/code/list.lisp index 225f1bb..a48af26 100644 --- a/src/code/list.lisp +++ b/src/code/list.lisp @@ -233,7 +233,8 @@ (defun last1 (list) #!+sb-doc "Return the last cons (not the last element) of a list" - (let ((rest list)) + (let ((rest list) + (list list)) (loop (unless (consp rest) (return list)) (shiftf list rest (cdr rest))))) @@ -275,7 +276,7 @@ (declare (type index size)) (do ((count size (1- count)) (result '() (cons initial-element result))) - ((zerop count) result) + ((<= count 0) result) (declare (type index count)))) (defun append (&rest lists) @@ -733,8 +734,8 @@ (do ((list list (cdr list))) ((null list) nil) (let ((car (car list))) - (if (satisfies-the-test item car) - (return list)))))) + (when (satisfies-the-test item car) + (return list)))))) (defun member-if (test list &key key) #!+sb-doc @@ -1156,3 +1157,43 @@ #!+sb-doc "Apply FUNCTION to successive CDRs of lists. Return NCONC of results." (map1 function (cons list more-lists) :nconc nil)) + +;;;; Specialized versions + +;;; %MEMBER-* and %ASSOC-* function. The transforms for %MEMBER and %ASSOC pick +;;; the appropriate version. These win because they have only positional arguments, +;;; the TEST & KEY functions are known to exist (or not), and are known to be +;;; functions, not function designators. +(macrolet ((def (funs form) + (flet ((%def (name) + `(defun ,(intern (format nil "%~A~{-~A~}" name funs)) + (item list ,@funs) + ,@(when funs `((declare (function ,@funs)))) + (do ((list list (cdr list))) + ((null list) nil) + (let ((this (car list))) + ,(ecase name + (assoc + `(when this + (let ((target (car this))) + (when (and this ,form) + (return this))))) + (member + `(let ((target this)) + (when ,form + (return list)))))))))) + `(progn + ,(%def 'member) + ,(%def 'assoc))))) + (def () + (eql item target)) + (def (key) + (eql item (funcall key target))) + (def (key test) + (funcall test item (funcall key target))) + (def (key test-not) + (not (funcall test-not item (funcall key target)))) + (def (test) + (funcall test item target)) + (def (test-not) + (not (funcall test-not item target))))