Каково объяснение упражнения 1.6 в SICP?
Вопрос
Я только начинаю работать через SICP (самостоятельно;это не для класса), и я уже пару дней мучаюсь с упражнением 1.6 и просто не могу в этом разобраться.Это тот, где Алисса переосмысливает if
с точки зрения cond
, вот так:
(define (new-if predicate then-clause else-clause)
(cond (predicate then-clause)
(else else-clause))
Она успешно тестирует его в нескольких простых случаях, а затем использует его для переписывания программы извлечения квадратного корня (которая прекрасно работала с if
):
(define (sqrt-iter guess x)
(new-if (good-enough? guess x)
guess
(sqrt-iter (improve guess x)
x)))
Тогда возникает вопрос:«Что произойдет, когда Алисса попытается использовать это для вычисления квадратных корней?Объясните." [При необходимости я с удовольствием воспроизведу остальные процедуры(good-enough?
, improve
, и т. д.), просто дайте мне знать.]
Теперь я знаю, что происходит:он никогда не возвращает значение, а это означает, что программа работает бесконечно.Я просто не могу объяснить, почему это происходит.Какая бы тонкая разница ни существовала между if
и new-if
ускользает от меня.Любая помощь очень ценится.
Решение
new-if
это функция.Что первое, что делает Scheme со списком аргументов при вызове функции?Он оценивает все аргументы.
Другие советы
new-if
является процедурой, и Scheme использует оценку аппликативного порядка (1.1.5), поэтому еще до new-if
фактически выполняется, он должен сначала оценить все аргументы, которые guess
и (sqrt-iter (improve guess x) x)
.Вы можете видеть, что последний аргумент представляет собой рекурсию, которая вызывает новый new-if
процедура, именно так происходит бесконечный цикл.
Обычный if
не нужно сначала оценивать свои аргументы, просто идти по пути, в этом разница между if
и new-if
. :)
Прежде всего вам придется понять разницу между оценкой аппликативного порядка и нормальным порядком.Лисп использует аппликативный порядок, но условные выражения оцениваются не так, как обычные функции (sicp глава 1.1.6):
(if <predicate> <consequent> <alternative>)
Чтобы вычислить выражение if, интерпретатор начинает с вычисления
<predicate>
часть выражения.Если<predicate>
вычисляет истинное значение, затем интерпретатор вычисляет<consequent>
и возвращает его значение.В противном случае он оценивает<alternative>
и возвращает его значение.
Пр1.6.новый-если:
(define (new-if predicate then-clause else-clause)
(cond (predicate then-clause)
(else else-clause)))
Разница с «if-операторами»:Операторы if оцениваются один за другим из предиката -> следствия -> альтернативы,
однако «new-if» должен оценивать все параметры, то есть аргументы, в МОМЕНТ, который он вызывает (что означает, что «else-предложение» оценивается в начале!!),
и, таким образом, это вызывает бесконечный цикл, когда любой из этих параметров вызывает себя в итеративный цикл.