The syntax for define
is not (define procedure arg .. body)
. It is either (define (name . args) defines ... body1 bodyn ...)
which is a shortcut for (define name (lambda args defines ... body1 bodyn ...))
. Note that x ...
means zero or more so (lambda (a b) (+ a b))
is fine but (lambda (a b) (define (test) (+ a b)))
isn't.
Internal define
is handled by the lambda
syntax. Basically it gets rewritten to a letrec
. So
(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))
Becomes:
(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))))
Obviously the reason for using local define
is to keep it flatter and more readable than letrec
. Keeping the same name even though they are totally different beasts that are handled by different parts of the implementation is a simplification for scheme programmers but harder to grasp and understand if you try to figure out how scheme implementations work.