我目前正在阅读Mike Vanier关于 Y-combinator 的这篇文章。
在 Y-combinator 推导的过程中,这段代码:
(define (part-factorial self)
(lambda (n)
(if (= n 0)
1
(* n ((self self) (- n 1))))))
((part-factorial part-factorial) 5) ==> 120
(define factorial (part-factorial part-factorial))
(factorial 5) ==> 120
被制定为:
(define (part-factorial self)
(let ((f (self self)))
(lambda (n)
(if (= n 0)
1
(* n (f (- n 1)))))))
(define factorial (part-factorial part-factorial))
(factorial 5) ==> 120
在那之后,文章指出:
这在惰性语言中可以正常工作。在严格的语言中,
(self self)
let 语句中的调用会将我们送入无限循环,因为为了计算(part-factorial part-factorial)
(在阶乘的定义中),您首先必须计算(部分阶乘部分阶乘)(在let
表达式中) .
然后读者受到挑战:
为了好玩:弄清楚为什么这不是以前的定义的问题。
在我看来,我已经弄清楚了原因,但我想确认一下:
- 我的理解是正确的。
- 据我了解,我不会错过任何关键点。
我的理解是:在第一个代码片段中,(self self)
调用不会导致无限循环,因为它被包含(包装)lambda
为一个part-factorial
函数,因此被评估为lambda (n)
直到实际进行调用(self self)
,这仅发生在n > 0
. 因此,在(= n 0)
评估为之后#t
,无需调用(self self)
。