letrec は局所関数を定義する一般的な方法だそうだ。
cf. 7. 繰り返し – もうひとつの Scheme 入門
let と違って定義内で自分の名前を参照できるので、再帰関数を定義することができる。
例を示そう。↓これは以前書いた take。define を使って局所関数 f を定義している。
(define take (lambda (n lis) (define f (lambda (m l1 l2) (if (= m 0) (reverse l2) (f (- m 1) (cdr l1) (cons (car l1) l2))))) (f n lis '())))
これを letrec を使って書き直すとこうなる。
(define take (lambda (n lis) (letrec ((f (lambda (m l1 l2) (if (= m 0) (reverse l2) (f (- m 1) (cdr l1) (cons (car l1) l2)))))) (f n lis '())))) (print (take 2 '(1 2 3 4 5)))
3行目(から6行目)で局所関数に f という名前をつけている。そして6行目でその f を再帰的に呼び出している。
実行結果:
^o^ > gosh take-letrec.scm (1 2)