块结构中的内部定义

时间:2017-07-12 03:11:26

标签: scheme sicp

(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的语法是:(define procedure arg arg body)。您如何在顶级定义中定义所有其他局部范围变量?

定义是否存在语法异常?

1 个答案:

答案 0 :(得分:0)

define的语法不是(define procedure arg .. body)。它是(define (name . args) defines ... body1 bodyn ...),是(define name (lambda args defines ... body1 bodyn ...))的快捷方式。请注意,x ...表示零或更多,因此(lambda (a b) (+ a b))可以正常,但(lambda (a b) (define (test) (+ a b)))不是。

内部definelambda语法处理。基本上它会被重写为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更平坦,更易读。保持相同的名称,即使它们是由实现的不同部分处理的完全不同的动物,也是方案程序员的简化,但是如果你试图弄清楚方案实现如何工作则更难理解和理解。