Prompt
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 of cond
” she asks. Alyssa’s friend Eva Lu Ator claims this can indeed be done, and she defines a new version of if
:
(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)))
What happens when Alyssa attempts to use this to compute square roots? Explain.
Solution
The new-if
appears to work since in the simple example we’re getting the correct results. However, the applicative order of evaluation of the new-if
is a subtle but important difference compared to the actual if
statement.
With applicative order evaluation of function applications, both the then-clause and the else-clause gets executed. We’re going to end up always evaluating sqrt-iter
even if the guess is good enough. This completely breaks recursive procedures that rely on the satisfaction of base case conditions to terminate calls. In this case, the recursive calls will never end because sqrt-iter
will be called all the time.
I really like this exercise because at a glance, it seems perfectly reasonable to implement if
in terms of cond
– I mean, they both exhibit the evaluation style that you want. else
clauses won’t be executed at all if the predicate is true. So why not just substitute one for the other?! That sounds good! But in trying to do this by defining a new function, you immediately lose the special-case evaluation behavior 😹. This really further drives home the essential nature of lazy evaluation behavior for conditionals.
I think often as consumers of programming languages we take this behavior for granted and don’t think twice about how conditional expressions are evaluated. But this sort of exercise (and many exercises in SICP!) puts you in the seat of the language designer.