[英]Why does wrapping a function with a lambda fix stack overflow?
如果expression求值是一个参数的函数,我会认为lambda x:( expression )(x)与expression相同-但实际上并非如此。 考虑Y组合器的以下两个定义:
def Y1(F):
left = lambda x: x(x)
right = lambda x: F(x(x))
return left(right)
def Y2(F):
left = lambda x: x(x)
right = lambda x: lambda y: (F(x(x)))(y)
return left(right)
Y2实际上按预期工作,但是调用Y1会引起堆栈溢出。 为什么在行为上有这种差异?
不, lambda x: (expression)(x)
与expression
并不相同。
它是一个函数,在调用时将返回expression
的结果,而不同于立即返回其结果的expression
。
那是什么结果? 它是一个参数的函数。 但这还不存在。 它需要构造,计算。 这就是expression
作用。 它计算表示“下一个”递归调用的递归函数,该递归函数可能需要由Y组合器构造的递归函数来完成 。
Y1
试图过早,过分急切地找到right
的值-它试图在返回计算的递归函数之前执行此操作。 因此,它永远不会返回,因为Y1
总是在返回前一个递归函数之前尝试计算下一个递归函数,以便可以对其进行调用。
但Y2
构建递归函数, 将计算时,将需要它的下一个递归函数; 但还不是“现在”。 它将其构造为lambda函数,这会延迟实际计算。 lambda函数的构建是一个简单的一步过程,该过程很快完成,然后返回计算出的递归函数,因此可以使用它,并且仅当/何时它将确定下一级别的递归调用需要在执行该操作时,它将在该时间点调用该lambda, 以在该时间 点即在调用它之前构造下一个递归函数。
不是这样的方式提前为Y1
正在试图做的事。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.