3

在 Scheme 中,我将基本的“if”命令修改为:

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

然后我使用 if 的修改版本定义了一个简单的阶乘生成程序:

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

现在,当我调用上述函数时,它进入了一个无限循环。为什么会这样?

4

2 回答 2

7

方案有热切的评价。这意味着,除非您使用特殊形式 (like ) 或委托给这种特殊形式if的宏 (like condor ),否则首先计算所有子表达式。case

这意味着你的表达

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

(* n (factorial (- n 1)))评估,然后modified-if再运行。(它可能在之前或之后运行(= n 0),但无论哪种方式都没有关系,递归调用仍然会发生。)并且由于这是一个递归调用,这意味着您的程序将无限递归,并且您最终会用完堆。

这是一个简单的例子:考虑这个:

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

因为if是一种特殊形式,它只评估必要的分支,在这种情况下它只会评估(display "Yay!")而不评估(error "Oh noes!")。但是如果你切换到使用你的modified-if,两个表达式都会被计算,你的程序会抛出一个错误。

于 2013-04-29T11:57:53.300 回答
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: enter image description here

于 2013-04-29T12:45:28.670 回答