为什么这个Racket代码没有终止?

时间:2014-10-21 21:08:47

标签: scheme racket

我正在阅读关于懒惰评估的内容,并且无法理解他们给出的基本示例。

#lang racket
(define (bad-if x y z)
  (if x y z))
(define (factorial-wrong x)
  (bad-if (= x 0)
          1
          (* x (factorial-wrong (- x 1)))))

(factorial-wrong 4)

我对这个程序永远不会终止的原因感到有些困惑。我知道下面的代码工作正常:

(define (factorial x)
  (if (= x 0)
      1
      (* x (factorial (- x 1)))))

(factorial 4)

所以我假设它与范围有关。我尝试了一步一步的调试,即使x被映射到0,factorial-wrong也会执行递归函数。

2 个答案:

答案 0 :(得分:5)

标准if

(if test-expr then-expr else-expr)

仅评估 then-expr else-expr,具体取决于test-expr,因为此if要么基于特殊表单的特殊表单语法扩展,这意味着它不遵循正常的评估规则。

另一方面,

bad-if是一个标准程序。在这种情况下,Scheme首先评估两个表达式,因为它们是实际执行bad-if之前的过程bad-if 的参数。因此,即使对于x = 0,也会评估(* x (factorial -1)),然后在无限循环中评估(* x (factorial -2)),依此类推。

答案 1 :(得分:4)

使用步进器!

更具体一点:

  • 从程序顶部剪切#lang球拍
  • 将语言级别更改为“中级学生”
  • 单击“步骤”按钮。仔细观察,看看哪些东西脱轨。