Paste number 143164: explain and

Index of paste annotations: 1

Paste number 143164: explain and
Pasted by: pjb
When:7 years, 10 months ago
Share:Tweet this! | http://paste.lisp.org/+32GS
Channel:None
Paste contents:
Raw Source | XML | Display As

(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>

Annotations for this paste:

Annotation number 1: correction
Pasted by: pjb
When:7 years, 10 months ago
Share:Tweet this! | http://paste.lisp.org/+32GS/1
Paste contents:
Raw Source | Display As
(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))

Colorize as:
Show Line Numbers

Lisppaste pastes can be made by anyone at any time. Imagine a fearsomely comprehensive disclaimer of liability. Now fear, comprehensively.