First of all, this question is based on the procedures good-enough?
,
improve
, guess
, improve
, and sqrt-iter
that have just been
written in the section prior to the exercise.
These procedures are layed out below:
(define (average x y)
(/ (+ x y) 2)
)
(define (improve guess x)
(average guess (/ x guess))
)
(define (square x)
(* x x)
)
(define (good-enough? guess x)
(< (abs (- (square guess) x)) 0.001)
)
(define (sqrt-iter guess x)
(if (good-enough? guess x)
guess
(sqrt-iter (improve guess x) x)
)
)
(define (sqrt x)
(sqrt-iter 1.0 x)
)
Alyssa P. Hacker doesn't see why
if
needs to be provided as a special form. "Why can't I just define it as an ordinary procedure in terms ofcond
?" she asks. Alyssa's friend Eva Lu Ator claims this can indeed be done, and she defines a new version ofif
:
(define (new-if predicate then-clause else-clause)
(cond (predicate then-clause) (else else-clause))
)
Eva demonstrates the program for Alyssa:
(new-if (= 2 3) 0 5)
; 5
(new-if (= 1 1) 0 5)
; 0
Delighted, Alyssa uses new-if to rewrite the square-root program:
(define (sqrt-iter guess x)
(new-if (good-enough? guess x)
guess
(sqrt-iter (improve guess x)
x
)
)
)
If one tries to run the program above with that alteration, it will never resolve as it will turn into an infinite loop.
The else-clause
includes a recursion to the function itself, and the Scheme
interpreter can't deal with recursions in this way as shown in exercise 1.5.
With the new-if
function being a procedure, the interpreter will try to
evaluate both arguments before applying the reduction due to the
applicative-order evaluation nature of the interpreter.
The if
conditional is different. It only evaluates the predicate and then
it evaluates which condition needs to run next.
Essentially, it is not possible to mimic the cond
and if
operators because
they do not follow applicative-order evaluation.