4
(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.0001))

(define (square x)
  (* x x))

(define (sqrt-g x)
  (sqrt-iter 1.0 x))

This is a program for sqrt. And the question is what happens when you attempts to use new-if to replace if with new-if.

(define (sqrt-iter guess x)
    (if (good-enough? guess x)
        guess
        (sqrt-iter(improve guess x)
                  x)))

This is new if

 (define (new-if predicate then-clause else-clause)
      (cond (predicate then-clause)
            (else else-clause)))

My opinion is the result of two program gonna be the same. because new-if and if can produce the same results.

However, new-if proved wrong, because it is a dead circle when I tried.

So, why?

leppie
  • 109,129
  • 16
  • 185
  • 292
Jerry Zhao
  • 255
  • 4
  • 10
  • Note that this is an SICP question, exercise 1.6. Consider the effect of applicative order evalation on uses of new-if. – dyoo Sep 17 '12 at 06:02

3 Answers3

9

new-if is a function. All the arguments to a function are evaluated before calling the function. But sqrt-iter is a recursive function, and you need to avoid making the recursive call when the argument is already good enough.

The built-in if is syntax, and only evaluates the then-branch or else-branch, depending on the value of the condition.

You can use a macro to write new-if.

Barmar
  • 596,455
  • 48
  • 393
  • 495
  • Indeed, by merely changing `define` to `define-syntax-rule` for the `new-if` declaration, it will work as expected. (Assuming that you're using `#lang racket`) – Dan Burton Sep 17 '12 at 06:30
  • "Syntax" is a bit imprecise. `If` is a _special operator_. – Svante Sep 17 '12 at 20:04
  • 2
    Racket looks like a Scheme dialect, and Scheme uses the term "syntax". – Barmar Sep 17 '12 at 22:01
  • 1
    That's it! I got it. That means before new-if , the recursive structure has run. So it is a dead circle. But the if just follow the normal order, just to evalulate good enough first, and then make the choice. Thank you! – Jerry Zhao Sep 19 '12 at 04:50
3

This is the perfect example for demonstration the algebraic stepper! In the the algebraic stepper you can see how the course of the computation differs from your expectation. Here you must pay notice to the differences in evaluation of, say, (new-if 1 2 3) and (if 1 2 3).

If you haven't tried the algebraic stepper before, see this answer to see what it looks like.

Community
  • 1
  • 1
soegaard
  • 28,660
  • 4
  • 50
  • 97
0

Since racket is an applicative procedure the 3rd argument to the new-if is (sqrt-iter(improve guess x) x)). Since sqrt-iter is recursive the 3rd argument never has a value assigned to it. Therefore you never move into the procedure of new-if to evaluate the function.

sat1017
  • 99
  • 1
  • 6