Exercise#
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:
1
2
3
|
(define (new-if predicate then-clause else-clause)
(cond (predicate then-clause)
(else else-clause)))
|
Eva demonstrates the program for Alyssa:
1
2
3
4
5
|
(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:
1
2
3
4
5
|
(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.
Student Response#
Looking at this code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
;code from previous sections
(define (square x) (* x x))
(define (sqrt-iter guess x)
(if (good-enough? guess x)
guess
(sqrt-iter (improve guess x)
x)))
(define (improve guess x)
(average guess (/ x guess)))
(define (average x y)
(/ (+ x y) 2))
(define (good-enough? guess x)
(< (abs (- (square guess) x)) 0.001))
(define (sqrt x)
(sqrt-iter 1.0 x))
;1.6
(define (new-if predicate then-clause else-clause)
(cond (predicate then-clause)
(else else-clause)))
(new-if (= 2 3) 0 5)
(new-if (= 1 1) 0 5)
(define (sqrt-iter guess x)
(new-if (good-enough? guess x)
guess
(sqrt-iter (improve guess x)
x)))
|
When Alyssa attempts to use this to compute square roots, the program will never terminate. It doesn’t terminate because it is not if
which is special form that evaluates the consequent or alternative expression, but new-if
which is an ordinary procedure and will evaluate both the consequent and alternative expression.
Evaluation
Critique my response and provide any nuance or detail that I am overlooking. Explain in detail.
Your response is on the right track, but let’s add some important nuance to make the explanation more complete and precise:
-
Applicative Order Evaluation: The key detail to emphasize is that Scheme uses applicative-order evaluation (evaluate the arguments first, then apply the procedure). This is crucial to understanding why new-if
fails.
-
Special Form vs. Regular Procedure: Your explanation about if
being a special form is correct, but we can elaborate:
if
is a special form that only evaluates the selected branch
new-if
, as a regular procedure, evaluates ALL its arguments before executing the procedure body
- This means both
then-clause
and else-clause
are evaluated regardless of the predicate’s value
-
Infinite Recursion Explanation: We can be more specific about why it never terminates:
- In
sqrt-iter
, the else-clause
contains a recursive call
- Because
new-if
evaluates all arguments, it will always evaluate the recursive call
- This happens before
new-if
even checks the predicate
- This leads to infinite recursion regardless of whether the guess is good enough
Here’s a more detailed response:
1
2
3
4
5
6
7
8
9
10
11
|
When Alyssa attempts to use this to compute square roots, the program enters an infinite recursion. This occurs because `new-if` is a regular procedure, not a special form like `if`. In Scheme's applicative-order evaluation:
1. All arguments to a procedure are evaluated before the procedure is applied
2. When `new-if` is called, it evaluates:
- The predicate `(good-enough? guess x)`
- The then-clause `guess`
- The else-clause `(sqrt-iter (improve guess x) x)`
The crucial problem is that the else-clause (the recursive call) is always evaluated, even when the guess is good enough. This creates an infinite chain of recursive calls, as each `new-if` evaluation spawns another `sqrt-iter` call before it can even check if the current guess is good enough.
This is why `if` must be a special form - it needs to break the normal evaluation rules to conditionally evaluate only one of its branches based on the predicate's value.
|
This explanation better captures the underlying mechanism of why the code fails and helps readers understand the importance of special forms in the language.