简体   繁体   English

为什么用lambda修复堆栈包装函数会溢出?

[英]Why does wrapping a function with a lambda fix stack overflow?

If expression evaluates to a function of one argument, I would have thought that lambda x: ( expression )(x) is identical to expression - but this is not actually the case. 如果expression求值是一个参数的函数,我会认为lambda x:( expression )(x)与expression相同-但实际上并非如此。 Consider the two following definitions of the Y combinator: 考虑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 actually works as expected, but calling Y1 raises a stack overflow. Y2实际上按预期工作,但是调用Y1会引起堆栈溢出。 Why is there this difference in behavior? 为什么在行为上有这种差异?

No, lambda x: (expression)(x) is not identical to expression . 不, lambda x: (expression)(x)expression并不相同。

It is a function that will return the result of expression when called, unlike expression that returns its result right away. 它是一个函数,在调用时返回expression的结果,而不同于立即返回其结果的expression

What is that result? 那是什么结果? It is a function of one parameter. 它是一个参数的函数。 But it's not there quite yet. 但这还不存在。 It needs to be constructed, calculated. 它需要构造,计算。 And that's what expression is doing. 这就是expression作用。 It calculates that recursive function representing the "next" recursive call that might need to be done by the recursive function constructed by Y combinator. 它计算表示“下一个”递归调用的递归函数,该递归函数可能需要Y组合器构造的递归函数来完成

Y1 tries to find the value of right prematurely, too soon, too eagerly -- it tries to do this before returning the calculated recursive function. Y1试图过早,过分急切地找到right的值-它试图返回计算的递归函数之前执行此操作。 Which is thus never returned, because Y1 always tries to calculate the next recursive function before returning the previous one so it can be called. 因此,它永远不会返回,因为Y1总是在返回前一个递归函数之前尝试计算下一个递归函数,以便可以对其进行调用。

But Y2 constructs the recursive function that will calculate the next recursive function when it will be needed; Y2构建递归函数, 计算时,将需要下一个递归函数; but not yet, not "now". 但还不是“现在”。 It constructs it as the lambda function, which delays the actual calculation. 它将其构造为lambda函数,这会延迟实际计算。 The construction of a lambda function is a simple one-step process which completes quickly, and then the calculated recursive function is returned, so it can be used -- and only if/when it will determine that the next level of recursive call needs to be performed, it will call that lambda at that point in time to construct that next recursive function at that point in time , ie just before calling it. lambda函数的构建是一个简单的一步过程,该过程很快完成,然后返回计算出的递归函数,因此可以使用它,并且仅当/何时它将确定下一级别的递归调用需要在执行该操作时,它将在该时间点调用该lambda, 以在该时间 即在调用它之前构造下一个递归函数。

Not way way in advance as the Y1 is trying to do. 不是这样的方式提前为Y1正在试图做的事。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM