You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何这段递归阶乘Racket代码会引发无限递归?

为什么自定义的my-if-bad会导致阶乘函数无限递归?

核心原因在于Racket的求值规则差异:普通函数的参数是严格求值(应用序),而内置if是特殊形式,采用按需求值(也就是你说的“惰性求值”)。

先明确两个关键概念:

  • 应用序求值:调用普通函数时,会先把所有参数表达式全部计算出结果,再将结果传入函数体内执行。
  • 特殊形式的按需求值:像内置if这种特殊语法,不遵循普通函数的求值规则——它只会先计算条件表达式,然后根据条件的真假,只计算对应分支的表达式,另一个分支完全不会被求值。

拆解你的代码问题:

  1. my-if-bad是普通函数,不是特殊形式
    当调用(my-if-bad x y z)时,Racket会先把x、y、z三个参数的表达式全部计算完毕,再进入函数体执行里面的内置if。这就意味着,不管x是真还是假,y和z都会被提前求值。

  2. factorial-bad的无限递归过程
    比如调用(factorial-bad 5):

    • 首先要计算my-if-bad的三个参数:
      • 第一个参数(= 5 0)得到#f;
      • 第二个参数1得到1;
      • 第三个参数(* 5 (factorial-bad 4))——这里会触发递归调用(factorial-bad 4);
    • 调用(factorial-bad 4)时,同样会先计算第三个参数(* 4 (factorial-bad 3)),继续递归;
    • 哪怕当n减到0时,调用(factorial-bad 0)依然会先计算第三个参数(* 0 (factorial-bad -1)),然后继续递归到n=-1、n=-2……永远无法终止,因为递归分支在条件判断之前就被强制触发了。

对比内置if的正确行为

如果直接用内置if写阶乘:

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

当n=0时,内置if只会计算条件(= 0 0)得到#t,直接返回1,完全不会去计算(* 0 (factorial-good -1)),递归到此终止,不会出现无限循环。

内容的提问来源于stack exchange,提问作者jem do

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 03:25:21