问题描述
我正在尝试实现 Y 组合器 like in the definition by Curry。
此代码不起作用。它会导致无限递归。
F = (lambda f: (lambda x: (1 if x == 0 else (x * (f(x-1))))))
Y = (
lambda f:
(lambda x: f(x(x)))
(lambda x: f(x(x)))
)
Y(F)(3)
但是,这个确实有效:
Y = (
lambda f:
(lambda x: f(
lambda v: x(x)(v)
))
(lambda x: f(
lambda v: x(x)(v)
))
)
Y(F)(3)
为什么第一个不起作用,而第二个起作用?
解决方法
Python 急切地评估所有函数参数,这就是导致 Y 组合器无限递归的原因。如linked Wikipedia article中所述:
在严格的编程语言中,Y 组合子将扩展直到堆栈溢出,或者在尾调用优化的情况下永不停止。
为了防止这种“急切”,可以将直接函数调用 x(x)
替换为另一个 lambda 函数。隐藏在该 lambda 函数中可防止它直接求值。这就是您在第二个版本中所做的:lambda v: x(x)(v)
。这种形式被称为 Z 组合器(参见上面的维基百科文章)。
第一个字符串打印出以下错误:
RecursionError: maximum recursion depth exceeded in comparison
Fatal Python error: _Py_CheckRecursiveCall: Cannot recover from stack overflow.
Python runtime state: initialized
它会导致无限循环。