Recursion 在Scheme中修改基本if表达式。为什么它会进入一个无限循环?
在Scheme中,我将基本的“if”命令修改为:Recursion 在Scheme中修改基本if表达式。为什么它会进入一个无限循环?,recursion,lisp,scheme,infinite-loop,racket,Recursion,Lisp,Scheme,Infinite Loop,Racket,在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)))
(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)))))
现在,当我调用上面的函数时,它进入一个无限循环。为什么会发生这种情况?方案有着迫切的评估。这意味着,除非您使用的是委托给这种特殊形式的特殊形式(如
if
)或宏(如cond
或case
),否则将首先计算所有子表达式
那意味着你的表情
(modified-if (= n 0)
1
(* n (factorial (- n 1))))
首先计算(*n(阶乘(-n1)))
,然后在运行时修改。(它可以在(=n0)
之前或之后运行,但无论哪种方式,递归调用都会发生。)由于这是一个递归调用,这意味着您的程序将无限递归,最终将耗尽堆栈
这里有一个简单的例子:考虑这个:
(if #t
(display "Yay!")
(error "Oh noes!"))
因为如果是一种特殊形式,它只计算必要的分支,在这种情况下,它只计算(显示“耶!”)
,而不计算(错误“哦,不!”)
。但是如果您切换到使用修改的if
,这两个表达式都将被计算,并且您的程序将引发错误。使用DrRacket中的步进器查看修改的if的行为
选择“初学者”语言。输入以下程序,然后单击步进器图标:
(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)
现在,您可以一步一步地了解计算是如何发展的。请注意,modif
遵循函数应用规则
有关DrRacket步进器的外观示例: