延迟Y-Combinator中的抽象评估

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了延迟Y-Combinator中的抽象评估相关的知识,希望对你有一定的参考价值。

我有一些问题包围着评估推迟如何工作。我试图用Y-Combinator来理解它:

如果我们编写一个简单版本的Y-Combinator,我们会遇到无限递归的问题:

Ysimple = (lambda f : (lambda x : f(x(x))) (lambda x : f(x(x))))

当我们构建递归函数时,会出现问题:

almost_factorial = lambda f : lambda n : 1 if n == 0 else n * f(n-1)

factorial = Ysimp(almost_factorial) # <- infinite recursion

Ysimple =(lambda f :( lambda x:f(x(x)))(lambda x:f(x(x)))) [上一行重复995次] RecursionError:超出最大递归深度

但是我们可以在延迟抽象中包装第二个或两个f(x(x))表达式:

Ydelay = (lambda f : (lambda x : f(x(x))) (lambda x : f(lambda y: x(x)(y))) )

现在代码工作得很好。但为什么?

如果我们在文件中只有Ysimple,则不会对任何内容进行评估。所以我假设只评估作为顶级表达式的lambdas。

我做了一些手动评估步骤,但我没有看到他们发生延迟的原因:

Ysimple F =  (lambda f : (lambda x : f(x(x))) (lambda x : f(lambda y: x(x)(y)))) F
          -> (lambda x : F(x(x))) (lambda x : F(lambda y: x(x)(y)))
          -> F( (lambda x : F(lambda y: x(x)(y))) (lambda x : F(lambda y: x(x)(y))) )


Ydelay F =  (lambda f : (lambda x : f(x(x))) (lambda x : f(x(x)))) F
         -> (lambda x : F(x(x))) (lambda x : F(x(x)))
         -> F( (lambda x : F(x(x))) (lambda x : F(x(x))) )

延迟在哪里发生?在这两种情况下,F是顶级表达,并且在两种情况下lambda x都低于F。延迟lambda y扮演什么角色?

Edit:

同样,为什么延迟在第一行如何工作:

(lambda x : x(x)) (lambda y: lambda x : x(x)(y))
(lambda x : x(x)) (lambda x: x(x))
答案

当我们将lambda表达式转换为普通函数语法时,整个事情变得更加明显:

def f(x):                       # lambda x : x(x)
    return x(x)

def g(y):                       # lambda y: lambda x : x(x)(y)
    def fg(x):
        return (x(x))(y)
    return fg


f(g) # does not recurse infinitely

当我们手动评估对应于(lambda x : x(x)) (lambda y: (lambda x : x(x))(y))的表达式时,我们得到了

f(g) = g(g) = lambda x : x(x)(g)

同时评估对应于(lambda x : x(x)) (lambda y: y(y))产量的那个

f(f) = f(f) = f(f) = ...

我们现在可以看到为什么抽象会停止递归。

以上是关于延迟Y-Combinator中的抽象评估的主要内容,如果未能解决你的问题,请参考以下文章

由于休息api延迟,视图寻呼机中的第一个片段未显示

Eclipse 中的通用代码片段或模板

Android中切换标签片段之间的延迟

使用 Git 来管理 Xcode 中的代码片段

用于修补代码和评估代码质量的抽象语法树

片段未附加到上下文 - 延迟的 UI 更改