1

如果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 会引发堆栈溢出。为什么会有这种行为差异?

4

1 回答 1

2

不,lambda x: (expression)(x)不等同于expression

它是一个在调用时返回结果的函数expression,与expression立即返回其结果不同。

那是什么结果?它是一个参数的函数。但它还不存在。它需要构建,计算。这就是expression正在做的事情。它计算表示“下一个”递归调用的递归函数,可能需要Y组合器构造的递归函数完成。

Y1right过早地、过早地、急切地试图找到 的值——它会在返回计算出的递归函数之前尝试这样做。因此永远不会返回,因为Y1总是在返回前一个递归函数之前尝试计算下一个递归函数,以便可以调用它。

但是Y2构造递归函数,该函数在需要计算下一个递归函数;但还没有,不是“现在”。它将其构造为 lambda 函数,从而延迟了实际计算。lambda 函数的构造是一个简单的一步过程,快速完成,然后返回计算出的递归函数,因此可以使用它——并且只有当/何时确定一级递归调用需要执行时,它将在该时间点调用该 lambda以在该时间点构造下一个递归函数即在调用它之前。

不像他们试图做的那样提前。Y1

于 2019-07-16T14:28:10.783 回答