90 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			Common Lisp
		
	
	
	
	
	
			
		
		
	
	
			90 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			Common Lisp
		
	
	
	
	
	
(in-package :alexandria)
 | 
						|
 | 
						|
(defmacro if-let (bindings &body (then-form &optional else-form))
 | 
						|
    "Creates new variable bindings, and conditionally executes either
 | 
						|
THEN-FORM or ELSE-FORM. ELSE-FORM defaults to NIL.
 | 
						|
 | 
						|
BINDINGS must be either single binding of the form:
 | 
						|
 | 
						|
 (variable initial-form)
 | 
						|
 | 
						|
or a list of bindings of the form:
 | 
						|
 | 
						|
 ((variable-1 initial-form-1)
 | 
						|
  (variable-2 initial-form-2)
 | 
						|
  ...
 | 
						|
  (variable-n initial-form-n))
 | 
						|
 | 
						|
All initial-forms are executed sequentially in the specified order. Then all
 | 
						|
the variables are bound to the corresponding values.
 | 
						|
 | 
						|
If all variables were bound to true values, the THEN-FORM is executed with the
 | 
						|
bindings in effect, otherwise the ELSE-FORM is executed with the bindings in
 | 
						|
effect."
 | 
						|
    (let* ((binding-list (if (and (consp bindings) (symbolp (car bindings)))
 | 
						|
                             (list bindings)
 | 
						|
                             bindings))
 | 
						|
         (variables (mapcar #'car binding-list)))
 | 
						|
    `(let ,binding-list
 | 
						|
       (if (and ,@variables)
 | 
						|
           ,then-form
 | 
						|
           ,else-form))))
 | 
						|
 | 
						|
(defmacro when-let (bindings &body forms)
 | 
						|
    "Creates new variable bindings, and conditionally executes FORMS.
 | 
						|
 | 
						|
BINDINGS must be either single binding of the form:
 | 
						|
 | 
						|
 (variable initial-form)
 | 
						|
 | 
						|
or a list of bindings of the form:
 | 
						|
 | 
						|
 ((variable-1 initial-form-1)
 | 
						|
  (variable-2 initial-form-2)
 | 
						|
  ...
 | 
						|
  (variable-n initial-form-n))
 | 
						|
 | 
						|
All initial-forms are executed sequentially in the specified order. Then all
 | 
						|
the variables are bound to the corresponding values.
 | 
						|
 | 
						|
If all variables were bound to true values, then FORMS are executed as an
 | 
						|
implicit PROGN."
 | 
						|
  (let* ((binding-list (if (and (consp bindings) (symbolp (car bindings)))
 | 
						|
                           (list bindings)
 | 
						|
                           bindings))
 | 
						|
         (variables (mapcar #'car binding-list)))
 | 
						|
    `(let ,binding-list
 | 
						|
       (when (and ,@variables)
 | 
						|
         ,@forms))))
 | 
						|
 | 
						|
(defmacro when-let* (bindings &body body)
 | 
						|
  "Creates new variable bindings, and conditionally executes BODY.
 | 
						|
 | 
						|
BINDINGS must be either single binding of the form:
 | 
						|
 | 
						|
 (variable initial-form)
 | 
						|
 | 
						|
or a list of bindings of the form:
 | 
						|
 | 
						|
 ((variable-1 initial-form-1)
 | 
						|
  (variable-2 initial-form-2)
 | 
						|
  ...
 | 
						|
  (variable-n initial-form-n))
 | 
						|
 | 
						|
Each INITIAL-FORM is executed in turn, and the variable bound to the
 | 
						|
corresponding value. INITIAL-FORM expressions can refer to variables
 | 
						|
previously bound by the WHEN-LET*.
 | 
						|
 | 
						|
Execution of WHEN-LET* stops immediately if any INITIAL-FORM evaluates to NIL.
 | 
						|
If all INITIAL-FORMs evaluate to true, then BODY is executed as an implicit
 | 
						|
PROGN."
 | 
						|
  (let ((binding-list (if (and (consp bindings) (symbolp (car bindings)))
 | 
						|
                          (list bindings)
 | 
						|
                          bindings)))
 | 
						|
    (labels ((bind (bindings body)
 | 
						|
               (if bindings
 | 
						|
                   `(let (,(car bindings))
 | 
						|
                      (when ,(caar bindings)
 | 
						|
                        ,(bind (cdr bindings) body)))
 | 
						|
                   `(progn ,@body))))
 | 
						|
      (bind binding-list body))))
 |