Access outer variable inside a block and Y-combinator
Asked Answered
J

1

8

I hope you all to be fine. I'm implementing the fixed-point Y-combinator in Harbour and I'm having some troubles with it. Well, the Y-combinator can be defined by the lambda-calculus as:

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

I'm trying to apply memoization with Y-combinator by performance questions. My current implementation is:

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 ) ) }

Basically, I can't use statements inside blocks, but I can use expressions and it works just fine. I'm avoiding an infinite recursion and the limit going through by 0 to infinite.

Until this time, it compiles just fine, but when I'm trying to access a variable of an outer block, Harbour kicks me in Face!

To test the Y-combinator implementation, I try to apply a simple implemetation of fibonacci sequence, but when I return a block that receives a parameter G and implicitly returns a block that receives a parameter N, G becames unavailable for me and the compiler says me that "Outer codeblock variable is out of reach".

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

This would also allow me to curry blocks. My question is: how can I access an outer variable inside a block, in Harbour?

Jenifferjenilee answered 16/3, 2015 at 17:5 Comment(0)
J
4

In Harbour, Clipper and xBase-based programming languages, blocks never can refer to the variable of the parent block. Blocks are not closures. We can reach that by creating local storages and using them in the internal blocks:

Function TestOuterScope
  Local accA
  Local bAdd := { |A| accA := A, { |B| accA + B } }
  Return Eval( Eval( bAdd, 10 ), 20 )
Jenifferjenilee answered 19/8, 2015 at 13:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.