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

jee*_*ace 3 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)
Run Code Online (Sandbox Code Playgroud)

我有点困惑为什么这个程序永远不会终止.我知道下面的代码工作得很好:

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

(factorial 4)
Run Code Online (Sandbox Code Playgroud)

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

use*_*lpa 5

标准 if

(if test-expr then-expr else-expr)
Run Code Online (Sandbox Code Playgroud)

只会评估要么 then-expr 或者 else-expr根据test-expr,因为这if可以是一个特殊形式句法扩展基于一种特殊形式,这意味着它不遵循正常的评估规则上.

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

  • 没有if语句完全以相同的方式表现.不同之处在于你称之为坏 - 如果这是一个程序.这是强制进行额外评估的程序调用机制. (3认同)