X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcode%2Flist.lisp;h=a48af261437bfb0d53ce4361de1937a4de024055;hb=05d9e55946615d14fa26d276b29072931f9dc5b5;hp=f15ad9f8aa0fd68f770900b2d77d1847527397e9;hpb=abd50c820df25616883a6850df1780044365137e;p=sbcl.git diff --git a/src/code/list.lisp b/src/code/list.lisp index f15ad9f..a48af26 100644 --- a/src/code/list.lisp +++ b/src/code/list.lisp @@ -276,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) @@ -734,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 @@ -1157,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))))