Poco fa ho riprovato a trovare un modo piu' semplice per creare funzioni memoized in PHP senza troppi sforzi da parte del programmatore. Sono riuscito ad ottenere una funzione che genera funzioni memoized che somiglia lontanamente ad una
macro, ecco qui il codice, con il solito esempio di Fibonacci:
function memofunction($name,$arglist,$body) {
$prefix = "
\$__self = '__FUNCNAME__';
global \$__memo;
global \$__flag;
if (!isset(\$__memo)) {
\$__memo = Array();
\$__flag = Array();
}
\$__argv = func_get_args();
\$__argc = count(\$__argv);
\$__aux = '[\$__self]';
\$__aux2 = '';
for(\$__i = 0; \$__i < \$__argc; \$__i++) {
\$__aux .= '[\$__argv['.\$__i.']]';
\$__aux2 .= '\$__argv['.\$__i.'],';
}
\$__aux2 = trim(\$__aux2,',');
\$__issetmemo = eval('return isset(\$__memo'.\$__aux.');');
\$__issetflag = eval('return isset(\$__flag'.\$__aux.');');
if (!\$__issetflag) {
if (!\$__issetmemo) {
eval('\$__flag'.\$__aux.'=true;');
\$__retval = eval('return '.\$__self.'('.\$__aux2.');');
eval('unset(\$__flag'.\$__aux.');');
eval('\$__memo'.\$__aux.'=\$__retval;');
}
return eval('return \$__memo'.\$__aux.';');
}"."\n";
$body = str_replace("__FUNCNAME__",$name,$prefix).$body;
eval('function '.$name.' ('.$arglist.') {'.$body.'}');
}
memofunction('fib','$n', '
if ($n <= 2) return 1;
return fib($n-1)+fib($n-2);
');
echo(fib(30)."\n");
In pratica la funzione
memofunction che accetta come parametri
il nome della funzione, la lista di argomenti (separati da virgole
se piu' di uno), e il
corpo della funzione, crea una funzione
a cui prepende il codice necessario per la memoization.
Credo sia piu' o meno il limite massimo di automatismo che il PHP
riesca a dare da questo punto di vista.
Da notare la pesante carenza di un modo per definire stringhe
che sia
adatto a scrivere codice dentro. Infatti il corpo della
funzione viene racchiuso tra
' ' nell'esempio, ma questo non permette
di scrivere dentro dei caratteri
' non quotati.
Sarebbe stato molto piu' sensato se fuori dal contesto di
while
e altre strutture condizionali { e } potevano servire per la definizione
di stringhe letterali contenenti qualunque cosa... ma purtroppo PHP e' cosi'.
Tanto per capirci:
$a = {
quello che ti pare ...
bla bla "" ' ' ; yez!!
$b = {};
};
Avrebbe dovuto assegnare a
$a tutto quello che c'e' tra la prima { e la } chiusa corrispondente.
Ok dopo questo dichiaro chiusa la mia lotta contro i limiti del PHP
dal punto di vista della memoization. Tra qualche giorno invece seguira'
il secondo post della serie che tentera' di portare il PHP al limite
dal punto di vista di qualche altra diversa funzionalita'.