#scheme #lisp
#схема #lisp
Вопрос:
Я читаю метод Ньютона в 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))
Я в замешательстве, потому что, в моем понимании вложенности, «достаточно хорошо?» и «улучшить предположение» должны быть вложены
в тело «sqrt-iter», а «sqrt iter» должен быть помещен в тело «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)))
))
))
почему это не так.Я использую LISP
Ответ №1:
Обратите внимание, что sqrt-iter
это уже определено внутри тела sqrt
. Но то, как вы это написали, не имеет смысла, вы пытаетесь вызвать sqrt-iter
, но определяете его внутри вызова в качестве третьего параметра. Это неправильно:
(sqrt-iter 1.0 x (define (sqrt-iter ...)))
Вы должны определить ее перед вызовом, и вы не можете определить ее так, как если бы она была параметром, как часть вызова процедуры. Это правильный путь:
(define (sqrt-iter guess x) ...) ; first define
(sqrt-iter 1.0 x) ; after defining, you can call it
Ваше другое предложение имеет больше смысла, можно было бы определить good-enough?
и improve
внутри sqrt-iter
, но, возможно, это понятнее в том, как они написали это в книге. Это допустимо, но имеет тот недостаток, что good-enough?
и improve
будет переопределяться при каждом sqrt-iter
вызове:
(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))
Вам следует более внимательно прочитать раздел книги, в котором объясняется, как процедуры определяются и используются в Scheme, вы, кажется, путаете понятия, смешивая параметры, определения процедур и вызовы процедур.
Комментарии:
1. так что насчет «достаточно хорошо?» и «улучшить предположение», его можно поместить под определение «sqrt-iter», но не внутри тела, почему он не ставит «достаточно хорошо?» и «улучшить предположение» под «sqrt-iter»
2. @89085731 Я обновил свой ответ, их можно перемещать, но все же я предпочитаю исходную версию, как она приведена в книге — ее легче читать.
3. Меня беспокоит то, что если мы не поставим «достаточно хорошо» и «улучшить предположение» под «sqrt-iter», то эти две функции лежат на одном уровне «sqrt-iter», но не отношение вложенных
4. похоже, что для вложенной функции ее можно рассматривать как какую-то скрытую переменную, поэтому нам нужно вызвать ее перед использованием
5. Не беспокойтесь о вложенности 😉 используйте ее только в том случае, если таким образом вы можете избежать некоторых параметров при определении новых процедур. И будьте осторожны при вложении процедур, определения должны быть только в начале процедуры, а не в произвольных местах.