X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcode%2Fearly-extensions.lisp;h=065f5694c562075dccc16aecd91c82ea2450a674;hb=2b596efa9a6b08a22bbdcdf88198c5d2af1d0335;hp=523754f0615a291b92602d5db3b507f2ce35e0eb;hpb=9767de1cecfe50560fe1da69fd458b6148a66da3;p=sbcl.git diff --git a/src/code/early-extensions.lisp b/src/code/early-extensions.lisp index 523754f..065f569 100644 --- a/src/code/early-extensions.lisp +++ b/src/code/early-extensions.lisp @@ -288,7 +288,12 @@ ;; just define ASSQ explicitly in terms of more primitive ;; operations: (dolist (pair alist) - (when (eq (car pair) item) + ;; though it may look more natural to write this as + ;; (AND PAIR (EQ (CAR PAIR) ITEM)) + ;; the temptation to do so should be resisted, as pointed out by PFD + ;; sbcl-devel 2003-08-16, as NIL elements are rare in association + ;; lists. -- CSR, 2003-08-16 + (when (and (eq (car pair) item) (not (null pair))) (return pair)))) ;;; like (DELETE .. :TEST #'EQ): @@ -365,7 +370,7 @@ ;;; Iterate over the entries in a HASH-TABLE. (defmacro dohash ((key-var value-var table &optional result) &body body) - (multiple-value-bind (forms decls) (parse-body body nil) + (multiple-value-bind (forms decls) (parse-body body :doc-string-allowed nil) (let ((gen (gensym)) (n-more (gensym))) `(with-hash-table-iterator (,gen ,table) @@ -824,7 +829,7 @@ which can be found at .~:@>" (error 'simple-type-error ; maybe should be TYPE-BUG, subclass of BUG? :value value :expected-type type - :format-string "~@<~S ~_is not a ~_~S~:>" + :format-control "~@<~S ~_is not a ~_~S~:>" :format-arguments (list value type))) ;;; Return a function like FUN, but expecting its (two) arguments in @@ -1092,6 +1097,33 @@ which can be found at .~:@>" (let ((it ,test)) (declare (ignorable it)),@body) (acond ,@rest)))))) +;;; (binding* ({(name initial-value [flag])}*) body) +;;; FLAG may be NIL or :EXIT-IF-NULL +;;; +;;; This form unites LET*, MULTIPLE-VALUE-BIND and AWHEN. +(defmacro binding* ((&rest bindings) &body body) + (let ((bindings (reverse bindings))) + (loop with form = `(progn ,@body) + for binding in bindings + do (destructuring-bind (names initial-value &optional flag) + binding + (multiple-value-bind (names declarations) + (etypecase names + (null + (let ((name (gensym))) + (values (list name) `((declare (ignorable ,name)))))) + (symbol + (values (list names) nil)) + (list + (values names nil))) + (setq form `(multiple-value-bind ,names + ,initial-value + ,@declarations + ,(ecase flag + ((nil) form) + ((:exit-if-null) + `(when ,(first names) ,form))))))) + finally (return form)))) ;;; Delayed evaluation (defmacro delay (form)