8

我希望你们一切都好。我正在 Harbor 中实现定点Y 组合器,但遇到了一些麻烦。嗯,Y 组合器可以通过lambda 演算定义为:

Y = (λh.λF.F(λ x.((h(h))(F))(x))) (λh.λF.F(λ x.((h(h))(F))(x)))

我正在尝试通过性能问题应用 Y-combinator 的记忆。我目前的实现是:

Function YMem( bF, aCache )
   Local xAnswer
    If !lCache ; lCache := { } ; EndIf
    Return { |Arg| Iif( aCache[ Arg ] ;
        , /* then      */ aCache[ Arg ];
        , /* otherwise */ aCache[ Arg ] := ;
            Eval( Eval( bF, { |N| Eval( Eval( YMem, bF, aCache ), N ) } ), Arg ) ) }

基本上,我不能在块内使用语句,但我可以使用表达式,它工作得很好。我正在避免无限递归和从 0 到无限的限制。

直到这个时候,它编译得很好,但是当我试图访问一个外部块的变量时,Harbor 把我踢到了脸上!

为了测试 Y 组合器的实现,我尝试应用斐波那契序列的简单实现,但是当我返回一个接收参数G的块并隐式返回一个接收参数的块时,对我N来说G变得不可用并且编译器告诉我“外部代码块变量遥不可及”。

Function Main
    Local bFib := YMem( { |G| ;
        { |N| ;
            Iif( N == 0, 1, Iif( N == 1, 1, Eval( G, N - 1 ) + Eval( G, N - 2) ) );
        } ;
    } )
    Return

这也可以让我咖喱块。我的问题是:如何在 Harbour 中访问块内的外部变量?

4

1 回答 1

4

在 Harbour、Clipper 和基于 xBase 的编程语言中,块永远不能引用父块的变量。块不是闭包。我们可以通过创建本地存储并在内部块中使用它们来实现:

Function TestOuterScope
  Local accA
  Local bAdd := { |A| accA := A, { |B| accA + B } }
  Return Eval( Eval( bAdd, 10 ), 20 )
于 2015-08-19T13:50:35.707 回答