Schemeのnamed-letの記述例.いつものようにGaucheで実行確認.
named-let.scm
gosh> (define (sum x y l) ; named-letを使用しない.
(cond ((> x y) (reverse l))
(else
(sum (+ x 1) y (cons x l)))))
sum
gosh> (sum 3 11 '())
(3 4 5 6 7 8 9 10 11)
gosh> (define (sum x y l)
(let loop ((x x) (l l)) ; named-letを使用する.
(cond ((> x y) (reverse l))
(else
(loop (+ x 1) (cons x l))))))
sum
gosh> (sum 3 11 '())
(3 4 5 6 7 8 9 10 11)
gosh> (define sum ; lambda式のdefine形式にする.
(lambda (x y l)
(let loop ((x x) (l l)) ; named-letを使用する.
(cond ((> x y) (reverse l))
(else
(loop (+ x 1) (cons x l)))))))
sum
gosh> (sum 3 11 '())
(3 4 5 6 7 8 9 10 11)
gosh>
どれも同じ内容でどんどん長くなっているけど,本質は3番目かもしれないと思っていたり.つまり,無名関数であるlambda式で再帰関数が定義できるということで.たとえば,こんな記述が書けたり…してもあんまし意味ないか.むう.
※2020-08-02追記:いや,意味大いにあるか.map
に無名再帰関数を指定しているということではないか….
map-lambda.scm
gosh> (map (lambda (p)
(let loop ((x (car p)) (y (cadr p)) (l '()))
(cond ((> x y) (reverse l))
(else
(loop (+ x 1) y (cons x l))))))
'((1 5) (4 9) (3 8)))
((1 2 3 4 5) (4 5 6 7 8 9) (3 4 5 6 7 8))
gosh>
※2020-08-17追記:named-letをletrec
でマクロ定義してみた例.
gosh> (define-syntax nlet
(syntax-rules ()
((_ fn ((n v) ...) body)
(letrec ((fn (lambda (n ...) body))) (fn v ...)))))
# <undef>
gosh> (nlet loop ((n 40) (f1 0) (f2 1))
(if (= n 0) f1 (loop (- n 1) f2 (+ f1 f2))))
102334155
参考文献
- Practical Scheme:なんでもλ