On Lisp復習

5.5 Cdr部での再帰

マクロの方が良かったり、末尾再帰に及ばなかったりするので、プロトタイプや速度が重要でない場面で用いれとのこと

CL-USER 1 > 
(defun lrec (rec &optional base)
  (labels ((self (lst)
             (if (null lst)
                 (if (functionp base) (funcall base) base)
               (funcall rec
                        (car lst)
                        #'(lambda () (self (cdr lst))) ))))
    #'self))
LREC

CL-USER 2 >
(setq copy-list2 (lrec #'(lambda (x f) (cons x (funcall f)))) )
#<interpreted function SELF 216CB502>

CL-USER 3 > (setq a '(1 2 3))
(1 2 3)

CL-USER 4 > (eq a (funcall copy-list2 a))
NIL

CL-USER 5 >
;;ex. evenp
(setq find-if2 (lrec #'(lambda (x f) (if (evenp x) x (funcall f)))) )
#<interpreted function SELF 2173F382>

CL-USER 6 > (funcall find-if2 '(1 2 3))
2

5.6 部分ツリーでの再帰

CL-USER 1 > 
(defun ttrav (rec &optional (base #'identity))
  (labels ((self (tree)
             (if (atom tree)
                 (if (functionp base) (funcall base tree) base)
               (funcall rec
                        (self (car tree))
                        (if (cdr tree) (self (cdr tree))) ))))
    #'self))
TTRAV

CL-USER 2 > (setq copy-tree2 (ttrav #'cons))
#<interpreted function SELF 200FC6E2>

CL-USER 3 > (funcall copy-tree2 '(1 (2 3) (4) 5 (6 (7))))
(1 (2 3) (4) 5 (6 (7)))

CL-USER 4 >
(setq count-leaves (ttrav #'(lambda (x r) (+ x (or r 1))) 1))
#<interpreted function SELF 200F8902>

CL-USER 5 > (funcall count-leaves '(1 2 (3)))
5;;nil含む

CL-USER 6 > (setq flatten (ttrav #'nconc #'list))
#<interpreted function SELF 216F6112>

CL-USER 7 > (funcall flatten '((1 (2) 3) 4 (5)))
(1 2 3 4 5)
CL-USER 1 > 
(defun trec (rec &optional (base #'identity))
  (labels ((self (tree)
             (if (atom tree)
                 (if (functionp base) (funcall base tree) tree)
               (funcall rec
                        tree
                        #'(lambda () (self (car tree)))
                        #'(lambda () (if (cdr tree) (self (cdr tree)))) ))))
    #'self))
TREC

CL-USER 2 > 
(setq flatten
      (trec #'(lambda (o l r)
                (nconc (funcall l) (funcall r)) )
            #'list))
#<interpreted function SELF 216FCA92>

CL-USER 3 > 
(setq rfind-if-evenp
      (trec #'(lambda (o l r)
                (or (funcall l) (funcall r)) )
            #'(lambda (tree)
                (and (evenp tree) tree) )))
#<interpreted function SELF 2172D24A>

CL-USER 4 > (funcall rfind-if-evenp '(1 (3 (5 7) 2) 9))
2