2012-04-05 12 views
5

Mi chiedo se c'è un modo per implementare un generico "memoize" funzionale (come in una funzione con una funzione come input e una funzione come output, come decoratori di python) in grado di gestire anche cps funzioni stile.memoize continuation passing function function

per una funzione normale (come in "il valore risultante ritorna dal ritorno, i parametri sono solo per ingresso!") Una funzione Memoize può essere semplice come (in javascript)

function memoize(fun) { 
    var cache = {}; 
    return function() { 
     var args = Array.prototype.slice.call(arguments); 
     if (args in cache) 
      return cache[args]; 
     var ret = fun.apply(this, arguments); 
     cache[args] = ret; 
     return ret; 
    }; 
} 

ma una funzione in stile cps non può essere memoizzata dalla mia semplice funzione memoize, perché ho bisogno di valutare "di nuovo" gli argomenti della funzione type, conoscendo anche il parametro da passare ad essi.

Ad esempio, data la funzione

function cps(param, next) { 
    var ret = param + 1; 

    // setTimeout for simulate async behaviour 
    setTimeout(function() { 
      next(ret); 
    }, 0); 
} 

forse posso trovare che next è una funzione, ma la sua firma (beh ... forse, ma è difficile), e sicuramente non i parametri utilizzati nella funzione!

Qualcuno può dirmi che mi sbaglio? : D

Sono interessato ad essere in grado di memorizzare una mezza dozzina di funzioni in stile cps e non voglio confondere la logica inserendo una "cache" in ognuna di esse.

+0

se si passa una tabella hash come argomento della propria funzione (definendo n-coppie di chiave: valori), sarebbe semplicemente la logica per il proprio scopo? – fcalderan

+0

non è così semplice: sto usando le funzioni in stile cps perché ho a che fare con una chiamata ajax: continueIfTrue/continueIfFalse non sono chiamate direttamente dalle mie funzioni, sono registrate come callback e chiamate dal browser quando la risposta è tornata. .. Non riesco a vedere come usare un hashtable può aiutarmi (forse sono solo cieco: D illuminami!). –

risposta

2

Sono nuovo di CPS, ma penso che dovrete costruire le vostre funzioni in un modo particolare.

Le funzioni di CPS la seguente struttura (generalizzando dal vostro esempio):

function cps(param, next) { 
    var ret = someFunctionOfParam(param); 

    // setTimeout for simulate async behaviour 
    setTimeout(function() { 
     next(ret); 
    }, 0); 
} 

Quindi, si potrebbe utilizzare il memoizer di serie, e costruire la funzione CPS pure. Tenendo questo separato per il gusto di farlo, prima CPS-maker (presuppone l'ultimo argomento per le funzioni è sempre la funzione di passare a):

function cpsMaker(transformFunc) { 
    return function() { 
       var args = Array.prototype.slice.call(arguments); 
       var next = args.pop(); // assume final arg is function to call 
       var ret = transformFunc.apply(this,args); 
       // setTimeout for simulate async behaviour 
       setTimeout(function() { 
        next(ret); 
       }, 0); 
      } 
} 

E poi il memoizer può essere utilizzato in combinazione con esso:

function plusOne(val) { 
    return val+1; 
} 

var memoPlusOne = memoize(plusOne); 
var cpsMemPlusOne = cpsMaker(memoPlusOne); 

cpsMemPlusOne(3,function(n){console.log(n)}); 

Il punto è separare la memoizzazione della trasformazione dalla costruzione CPS.

Grazie per aver introdotto l'idea di CPS memoized; anche se questa risposta è spazzatura, è stata una rivelazione per me!

0

C'è un modo così generico di farlo, che viene presentato here in F #.