0.8.2.39:
[sbcl.git] / src / code / early-extensions.lisp
index 4888ae5..81b6f7b 100644 (file)
                       (t `(values ,@(cdr result) &optional)))))
     `(function ,args ,result)))
 
+;;; a type specifier
+;;;
+;;; FIXME: The SB!KERNEL:INSTANCE here really means CL:CLASS.
+;;; However, the CL:CLASS type is only defined once PCL is loaded,
+;;; which is before this is evaluated.  Once PCL is moved into cold
+;;; init, this might be fixable.
+(def!type type-specifier () '(or list symbol sb!kernel:instance))
+
 ;;; the default value used for initializing character data. The ANSI
 ;;; spec says this is arbitrary, so we use the value that falls
 ;;; through when we just let the low-level consing code initialize
   ;; 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):
@@ -816,7 +829,7 @@ which can be found at <http://sbcl.sourceforge.net/>.~:@>"
   (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)))
 \f
 ;;; Return a function like FUN, but expecting its (two) arguments in
@@ -1083,3 +1096,45 @@ which can be found at <http://sbcl.sourceforge.net/>.~:@>"
           `(if ,test
                (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))))
+\f
+;;; Delayed evaluation
+(defmacro delay (form)
+  `(cons nil (lambda () ,form)))
+
+(defun force (promise)
+  (cond ((not (consp promise)) promise)
+        ((car promise) (cdr promise))
+        (t (setf (car promise) t
+                 (cdr promise) (funcall (cdr promise))))))
+
+(defun promise-ready-p (promise)
+  (or (not (consp promise))
+      (car promise)))