I've just started reading SICP wherein Abelson/Sussman pose the
question, "Why is the 'if' special form necessesary when one could
define 'if' in terms of cond?" I've presented their scheme "define" as
a lisp "defun" below:
(defun new-if (predicate then-clause else-clause)
(cond (predicate then-clause)
(t else-clause)))
They go on to point out that the "new-if" construction works fine in
simple constructs like:
(defun my-max (x y)
(new-if (> x y)
x
y))
But it fails in cases like this:
(defun fact (x)
(new-if (zerop x)
1
(* x (fact (- x 1)))))
and results in infinite recursion.
My question is why the heck does this ···········@!
My guess is that the "pred" argument is acting like a lexical closure
and that "x" is being captured. Therefore, the predicate is testing
(zerop x) as opposed to (zerop (- x 1)). But this is just a guess. I'd
really love a solid answer.
Thanks,
- Ted
--
··········@att.net
Ted Sandler wrote:
> I've just started reading SICP wherein Abelson/Sussman pose the
> question, "Why is the 'if' special form necessesary when one could
> define 'if' in terms of cond?" I've presented their scheme "define" as
> a lisp "defun" below:
>
> (defun new-if (predicate then-clause else-clause)
> (cond (predicate then-clause)
> (t else-clause)))
>
> They go on to point out that the "new-if" construction works fine in
> simple constructs like:
>
> (defun my-max (x y)
> (new-if (> x y)
> x
> y))
>
> But it fails in cases like this:
>
> (defun fact (x)
> (new-if (zerop x)
> 1
> (* x (fact (- x 1)))))
>
> and results in infinite recursion.
>
> My question is why the heck does this ···········@!
>
> My guess is that the "pred" argument is acting like a lexical closure
> and that "x" is being captured. Therefore, the predicate is testing
> (zerop x) as opposed to (zerop (- x 1)). But this is just a guess. I'd
> really love a solid answer.
>
> Thanks,
> - Ted
>
>
It has to do with the order of argument evaluation. A special form is
special because it can control when its arguments are evaluated. An
ordinary function call on the other hand must have its arguments
evaluated before it is invoked. Your NEW-IF is a function, and its
arguments must be completely evaluated before it is invoked. In the
factorial function, you simultaneously evaluate the condition, the
then-clause and the else-clause. In the evaluation of the else-clause
you re-invoke your factorial function, without first having the
opportunity to test the return value of the condition! The special form
IF on the other hand will evaluate only one of the then-clause or
else-clause, as dictated by the value of the condition. So it will get
the opportunity to halt its computation at the right time.
Hope that helps.
Sunil
>>>>> "TS" == Ted Sandler <··········@worldnet.att.net> writes:
TS> I've just started reading SICP wherein Abelson/Sussman pose
TS> the question, "Why is the 'if' special form necessesary when
TS> one could define 'if' in terms of cond?" I've presented their
TS> scheme "define" as a lisp "defun" below:
TS> (defun new-if (predicate then-clause else-clause) (cond
TS> (predicate then-clause) (t else-clause)))
This should be covered in the section preceding that question.
I mean the bit about what happens to function arguments when the
function is called.
TS> [...] My question is why the heck does this ···········@!
[I deleted your theory] Trying (new-if (= x 0) x (1/x)) might help
you better than the factorial example to see why.
cheers,
BM
>>>>> "TS" == Ted Sandler <··········@worldnet.att.net> writes:
TS> I've just started reading SICP wherein Abelson/Sussman pose
TS> the question, "Why is the 'if' special form necessesary when
TS> one could define 'if' in terms of cond?" I've presented their
TS> scheme "define" as a lisp "defun" below:
TS> (defun new-if (predicate then-clause else-clause) (cond
TS> (predicate then-clause) (t else-clause)))
This should be covered in the section preceding that question.
I mean the bit about what happens to function arguments when the
function is called.
TS> [...] My question is why the heck does this ···········@!
[I deleted your theory] Trying (new-if (= x 0) x (/ 1 x)) with x bound
to 0 and 1 might help you better than the factorial example to see why.
cheers,
BM