Modification of the basic if expression in Scheme.

2019-02-24 19:40发布

问题:

In Scheme, I modified the basic 'if' command as:

(define (modified-if predicate then-clause else-clause)
  (if predicate
      then-clause
      else-clause))

And then I defined a simple factorial generating program using the modified version of if:

(define (factorial n)
  (modified-if (= n 0)
               (* n (factorial (- n 1)))))

Now, when I call the above function, it goes into an infinite loop. Why does that happen?

回答1:

Scheme has eager evaluation. This means that, unless you're using a special form (like if) or a macro (like cond or case) that delegates to such a special form, all subexpressions are evaluated first.

That means for your expression

(modified-if (= n 0)
             1
             (* n (factorial (- n 1))))

the (* n (factorial (- n 1))) is evaluated first, before modified-if is run. (It may be run before or after (= n 0), but it doesn't matter either way, the recursive call still happens regardless.) And since this is a recursive call, that means that your program will infinitely recurse, and you will eventually run out of stack.

Here's a simple example: consider this:

(if #t
    (display "Yay!")
    (error "Oh noes!"))

Because if is a special form, and it only evaluates the necessary branch, in this case it will only evaluate (display "Yay!") and not evaluate (error "Oh noes!"). But if you switch to using your modified-if, both expressions will be evaluated, and your program will raise an error.



回答2:

Use the stepper in DrRacket to see how your modified-if behaves.

Choose the "Beginner" language. Enter the program below, and then click the stepper icon:

(define (modif predicate then-clause else-clause)
  (if predicate then-clause else-clause))
(define (factorial n)
  (modif (= n 0) 1 (* n (factorial (- n 1)))))
(factorial 5)

You can now step for step see how the computation evolves. Notice that modif follows the rule of function application.

For an example of how the DrRacket stepper looks like: