(shadow 'and)
(defmacro and (&rest args)
(cond
((null args)
`(values t 'neutral-element))
((null (cdr args))
`(values ,(car args) `(the only subexpression of and is ,,(car args))))
(t
(let ((bn (gensym "and")))
`(block ,bn
,@(loop
:for l = (length args)
:for i :from 1
:for exp :in args
:for res = (gensym "res")
:for why = (gensym "why")
:collect `(multiple-value-bind (,res ,why) ,exp
(unless ,res
(return-from ,bn (values nil `(the ,,i th subexpression is ,,exp returns nil because ,,why)))))
:when (= i l)
:collect `(multiple-value-bind (,res ,why) ,exp
(values ,res `(the last subexpression is ,,exp returns ,,res because ,,why)))))))))
user1> (and 1 2 3)
3
(the last subexpression is 3 returns 3 because nil)
user1> (and 1 2 nil)
nil
(the 3 th subexpression is nil returns nil because nil)
user1> (and 1 2 (and 1 2 4))
4
(the last subexpression is 4 returns 4 because (the last subexpression is 4 returns 4 because nil))
user1>
(defmacro and (&rest args)
(cond
((null args)
`(values t 'neutral-element))
((null (cdr args))
`(values ,(car args) `(the only subexpression of and is ,,(car args))))
(t
(let ((bn (gensym "and")))
`(block ,bn
,@(loop
:for l = (length args)
:for i :from 1
:for exp :in args
:for res = (gensym "res")
:for why = (gensym "why")
:collect `(multiple-value-bind (,res ,why) ,exp
(unless ,res
(return-from ,bn (values nil `(the ,,i th subexpression is ,',exp returns nil because ,,why)))))
:when (= i l)
:collect `(multiple-value-bind (,res ,why) ,exp
(values ,res `(the last subexpression is ,',exp returns ,,res because ,,why)))))))))
user1> (and 1 2 (and 1 2 nil) 3 4)
nil
(the 3 th subexpression is (and 1 2 nil) returns nil because (the 3 th subexpression is nil returns nil because nil))