2015-03-16 6 views
8

J'espère que tout ira bien. J'applique le Y-combinator dans le port et j'ai quelques problèmes avec lui. Eh bien, le Y-Combinator peut être définie par le lambda-calcul comme:Accéder à la variable externe à l'intérieur d'un bloc et un combinateur Y

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

J'essaie d'appliquer memoization avec Y-Combinator par des questions de performance. Mon implémentation actuelle est:

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

Fondamentalement, je ne peux pas utiliser des instructions à l'intérieur des blocs, mais je peux utiliser des expressions et il fonctionne très bien. J'évite une récursion infinie et la limite passe de 0 à l'infini.

Jusqu'à maintenant, il se compile très bien, mais quand j'essaie d'accéder à une variable d'un bloc externe, Harbour me donne un coup de pied dans Face!

Pour tester la mise en œuvre Y-Combinator, j'essaie d'appliquer d'un simple Implémentation de la séquence fibonacci, mais quand je reviens un bloc qui reçoit un paramètre G et renvoie implicitement un bloc qui reçoit un paramètre N, G becames indisponible pour moi et le compilateur me dit que "la variable de codeblock externe est hors de portée".

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

Cela me permettrait également de bloquer les blocs. Ma question est: comment puis-je accéder à une variable externe à l'intérieur d'un bloc, à Harbour?

+0

@vittore Désolé? –

Répondre

4

dans le port, Clipper et langages de programmation-xBase, blocs ne peuvent se référer à la variable du bloc parent. Les blocs ne sont pas des fermetures. Nous pouvons atteindre cela par en créant des stockages locaux et en les utilisant dans les blocs internes:

Function TestOuterScope 
    Local accA 
    Local bAdd := { |A| accA := A, { |B| accA + B } } 
    Return Eval(Eval(bAdd, 10), 20)