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