修改Scheme中的基本if表达式.它为什么会进入无限循环?

Ran*_*eer 3 lisp recursion scheme infinite-loop racket

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

(define (modified-if predicate then-clause else-clause)
  (if predicate
      then-clause
      else-clause))
Run Code Online (Sandbox Code Playgroud)

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

(define (factorial n)
  (modified-if (= n 0)
               (* n (factorial (- n 1)))))
Run Code Online (Sandbox Code Playgroud)

现在,当我调用上面的函数时,它会进入无限循环.为什么会这样?

Chr*_*ung 7

Scheme急切评估.这意味着,除非您使用特殊形式(如if)或委托给这种特殊形式的宏(如condcase),否则首先评估所有子表达式.

这意味着你的表达

(modified-if (= n 0)
             1
             (* n (factorial (- n 1))))
Run Code Online (Sandbox Code Playgroud)

在运行(* n (factorial (- n 1)))之前首先评估modified-if.(它可以在之前或之后运行(= n 0),但无论哪种方式都无关紧要,递归调用仍然会发生.)因为这是一个递归调用,这意味着你的程序将无限递归,你最终会用完堆.

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

(if #t
    (display "Yay!")
    (error "Oh noes!"))
Run Code Online (Sandbox Code Playgroud)

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