define
の構文は(define procedure arg .. body)
ではありません。 (define name (lambda args defines ... body1 bodyn ...))
のショートカットである(define (name . args) defines ... body1 bodyn ...)
のいずれかです。 x ...
は0以上を意味するので、(lambda (a b) (+ a b))
は問題ありませんが、(lambda (a b) (define (test) (+ a b)))
は正しくありません。
内部define
は、lambda
構文で処理されます。基本的にはletrec
に書き換えられます。だから、
(define (sqrt x)
(define (good-enough? guess x)
(< (abs (- (square guess) x)) 0.001))
(define (improve guess x)
(average guess (/ x guess)))
(define (sqrt-iter guess x)
(if (good-enough? guess x)
guess
(sqrt-iter (improve guess x) x)))
(sqrt-iter 1.0 x))
は次のようになります。
(define sqrt
(lambda (x)
(letrec ((good-enough? (lambda (guess x)
(< (abs (- (square guess) x)) 0.001)))
(improve (lambda (guess x)
(average guess (/ x guess))))
(sqrt-iter (lambda (guess x)
(if (good-enough? guess x)
guess
(sqrt-iter (improve guess x) x)))))
(sqrt-iter 1.0 x))))
明らかローカルdefine
を使用する理由は、それが平らとletrec
より読みやすく維持することです。実装のさまざまな部分で扱われる全く異なる獣であっても、同じ名前を持つことはスキームプログラマーのための単純化ですが、スキーマ実装の仕組みを理解しようとすると理解しにくくなります。
使用しているスキームを知っておくと便利です。また、[この質問](https://stackoverflow.com/questions/20896471/decent-way-of-nested-definition-in-scheme)とその回答を確認することもできます。 – pdoherty926