and-let*を実装した

欲しくなったので,ぐぐったら2009-10-06が出てきたので,これを(大いに)参考にして実装してみた.
束縛値がnilの時にも即座にand-let*から抜けるようにした.

(and-let* ((x 10)
           (y nil))
  x)
;; => nil
(defmacro and-let* (exp &rest body)
  `(%and-let* ,exp ,body))

(defmacro %and-let* (exp body)
  (if (null exp)
      `(progn ,@body)
    (let* ((head (car exp))
           (tail (cdr exp))
           (form `(if ,(car head)
                     (%and-let* ,tail
                                ,body))))
      (if (and (consp head) (null (cdr head)))
          form
        `(let (,head)
           ,form)))))

(put 'and-let* 'lisp-indent-function 1)