So che questo potrebbe non essere un approccio semplice, ma ho imparato una tecnica chiamata "correzione" dai linguaggi funzionali. La fix
funzione di Haskell è conosciuta più in generale come il combinatore Y , che è uno dei più noti combinatori a punto fisso .
Un punto fisso è un valore invariato da una funzione: un punto fisso di una funzione f è qualsiasi x tale che x = f (x). Un combinatore a punto fisso y è una funzione che restituisce un punto fisso per qualsiasi funzione f. Poiché y (f) è un punto fisso di f, abbiamo y (f) = f (y (f)).
In sostanza, il combinatore Y crea una nuova funzione che accetta tutti gli argomenti dell'originale, oltre a un argomento aggiuntivo che è la funzione ricorsiva. Come funziona è più ovvio usando la notazione al curry. Invece di scrivere argomenti tra parentesi ( f(x,y,...)
), scriverle dopo la funzione: f x y ...
. Il combinatore Y è definito come Y f = f (Y f)
; o, con un singolo argomento della funzione ricorsivo, Y f x = f (Y f) x
.
Dato che PHP non carica automaticamente le funzioni, è un po 'un trucco per far fix
funzionare, ma penso che sia interessante.
function fix( $func )
{
return function() use ( $func )
{
$args = func_get_args();
array_unshift( $args, fix($func) );
return call_user_func_array( $func, $args );
};
}
$factorial = function( $func, $n ) {
if ( $n == 1 ) return 1;
return $func( $n - 1 ) * $n;
};
$factorial = fix( $factorial );
print $factorial( 5 );
Nota che è quasi uguale alle semplici soluzioni di chiusura che altri hanno pubblicato, ma la funzione fix
crea la chiusura per te. I combinatori a punto fisso sono leggermente più complessi rispetto all'uso di una chiusura, ma sono più generali e hanno altri usi. Mentre il metodo di chiusura è più adatto per PHP (che non è un linguaggio terribilmente funzionale), il problema originale è più un esercizio che per la produzione, quindi il combinatore Y è un approccio praticabile.
global $factorial
?