Search code examples
schemelisp

Nested function in programing


I am reading Newton's method in SICP, where he introduce the block structure which have the function nested, say

(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))

I am quite confused because in my understanding of nested, "good enough ?" and "improve guess" should be nested in the body of "sqrt-iter", and "sqrt iter" should be put in the body of "sqrt x"

(define (sqrt x)
   (sqrt-iter 1.0 x
      (define (sqrt-iter guess x)
        (if (good-enough? guess x)
        guess
        (sqrt-iter(improve guess x)x)
             (define (good enough ? guess x)
                 (<(abs(-(square guess) x)) 0.001))
             (define (improve guess x)
                 (average guess (/ x guess)))
       )) 
    ))

why it is not like that.I am using LISP


Solution

  • Notice that sqrt-iter is already defined inside the body of sqrt. But the way you wrote it doesn't make sense, you're trying to call sqrt-iter but you're defining it inside the call as a third parameter. This isn't right:

    (sqrt-iter 1.0 x (define (sqrt-iter ...)))
    

    You must define it before calling it, and you can't define it as if it were a parameter, as part of the procedure call. This is the correct way:

    (define (sqrt-iter guess x) ...) ; first define
    (sqrt-iter 1.0 x) ; after defining, you can call it
    

    Your other suggestion makes more sense, it'd be possible to define good-enough? and improve inside sqrt-iter, but maybe it's clearer in the way they wrote it in the book. This is valid, but has the disadvantage that good-enough? and improve will be redefined each time sqrt-iter is called:

    (define (sqrt x)
      (define (sqrt-iter guess x)
        (define (good-enough? guess x)
          (< (abs (- (square guess) x)) 0.001))
        (define (improve guess x)
          (average guess (/ x guess)))
        (if (good-enough? guess x)
            guess
            (sqrt-iter (improve guess x)x))) 
      (sqrt-iter 1.0 x))
    

    You should read more carefully the section of the book that explains how procedures are defined and used in Scheme, you seem to be confusing concepts, mixing parameters, procedure definitions and procedure invocations.