1

在这个 Y-combinator 的解释中(https://mvanier.livejournal.com/2897.html),

  (define almost-factorial
    (lambda (f)
      (lambda (n)
        (if (= n 0)
            1
            (* n (f (- n 1)))))))


  (define factorialA (almost-factorial factorialA))

它说阶乘 A 的定义将进入标准方案中的无限循环,但是实现它会给出一个错误,说阶乘 A 没有定义。

我认为这是预期的,因为当我们定义(如果不是使用 lambda)时,我们正在评估最终将计算参数的定义,其中一个是尚未定义的相同函数。

这是正确的,那么我们如何解释上面的文章呢?谢谢

4

2 回答 2

1

考虑表达式(define p M),其中M是某个表达式并且p是一个变量。

假设我们在 environment 中评估这个表达式E。评估(define p M)应该做两件事:

  1. 它应该M在环境中进行评估E;让结果成为x
  2. 它应该修改环境E,以便p绑定到x.

那么当我们在尚未定义(define factorialA (almost-factorial factorialA))的环境E中进行评估时会发生什么?factorialA

首先,我们尝试(almost-factorial factorialA)在环境中进行评估E。为此,我们首先评估almost-factorial,它成功了。然后我们进行评估factorialA,因为factorialA未在 environment 中定义而失败E。因此,整个事情应该会失败。

另一方面,如果我们尝试

(define (returns-factorialA) (almost-factorial (returns-factorialA)))
(define factorialA (returns-factorialA))

这确实会陷入无限循环。这可能是本文作者所寻找的。

于 2021-06-07T05:53:36.053 回答
0

从 SICP 的角度来看,这不是一个自引用过程,因为 factorialA 是一个值,而不是过程。

在第 4 章表示表达式开发了一个方案评估器,我们有:

(define (definition-value exp)
  (if (symbol? (cadr exp))
      (caddr exp)
      (make-lambda (cdadr exp)   ; formal parameters
                   (cddr exp)))) ; body

这意味着如果后面的表达式define是一个原始符号,factorialA那么它将立即评估表达式的主体并将其值分配给factorialA. 但如果它是一个类似(factorialA)or的列表,(factorialA n)那么它将创建一个 lambda 表达式。当计算 lambda 表达式时,会创建一个过程,这意味着仅在调用该过程时才计算主体。

于 2021-06-07T06:40:37.430 回答