6.6の「Programing Gauche p54のappend2という手続き」ところね。
普通(?)の再帰
定義と書きくだしてみたやつを載せてみる。最後まで計算しないと全然計算が進んでいないことに注目。
(define (length lis) (if (null? lis) 0 (+ 1 (length (cdr lis))))) (length '(1 2 3)) (+ 1 (length (cdr '(1 2 3)))) (+ 1 (length '(2 3))) (+ 1 (+ 1 (length (cdr '(2 3))))) (+ 1 (+ 1 (length '(3)))) (+ 1 (+ 1 (+ 1 (length (cdr '(3)))))) (+ 1 (+ 1 (+ 1 0)))
末尾再帰を使ったバージョン
ローカル手続きを使って定義するのだが、書きくだせなくなるので、とりあえず外でも定義しといた。まあ、この段階では問題ないからおk。理解優先。
(define (length lis) (define (length-rec lis n) (if (null? lis) n (length-rec (cdr lis) (+ n 1)))) (length-rec lis 0) ) (define (length-rec lis n) (if (null? lis) n (length-rec (cdr lis) (+ n 1)))) (length-rec lis 0) (length '(1 2 3)) (length-rec '(1 2 3) 0) (length-rec (cdr '(1 2 3)) (+ 0 1)) (length-rec '(2 3) 1) (length-rec (cdr '(2 3)) (+ 1 1)) (length-rec '(3) 2) (length-rec (cdr '(3)) (+ 2 1)) (length-rec '() 3) (length-rec '() 3) 3
最後まで行かなくってもちょびちょび計算できていることに注目。実質ループと手間は一緒と考えることができる。