So che questo potrebbe non essere un approccio semplice, ma ho imparato a conoscere una tecnica chiamata "fix" da linguaggi funzionali. La funzione fix
di Haskell è conosciuta più in generale come Y combinator, che è uno dei più noti fixed point combinators.
Un punto fisso è un valore che è invariata da una funzione: un punto fisso di una funzione f è qualunque x tale che x = f (x). Un combinatore a virgola fissa 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 prende tutti gli argomenti dell'originale, più un argomento aggiuntivo che è la funzione ricorsiva. Come funziona è più ovvio usare la notazione al curry. Invece di scrivere argomenti tra parentesi (f(x,y,...)
), scriverli dopo la funzione: f x y ...
. Il combinatore Y è definito come Y f = f (Y f)
; oppure, con un singolo argomento per la funzione ricorsiva, Y f x = f (Y f) x
.
Dal momento che PHP non esegue automaticamente le funzioni curry, è un po 'un trucco per rendere operativo il lavoro fix
, 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 questa è quasi la stessa di semplici soluzioni di chiusura altri hanno postato, ma la funzione fix
crea la chiusura per voi. I combinatori a punti fissi sono leggermente più complessi rispetto all'utilizzo 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ù di un esercizio che di produzione, quindi il combinatore Y è un approccio praticabile.
fonte
2010-05-05 14:19:03
Non ho PHP 5.3.0 da verificare, ma hai provato a utilizzare 'global $ factorial'? – kennytm
* (sidenote) * una Lamba è una funzione anonima, mentre quella precedente è una chiusura. – Gordon
Lambda e chiusure non si escludono a vicenda. In effetti alcune persone credono che una chiusura deve essere lambda perché sia una chiusura (funzione anonima). Ad esempio in Python è necessario assegnare prima un nome alla funzione (a seconda della versione).Perché devi dargli un nome che non puoi in linea e qualcuno direbbe che lo squalifica dall'essere una chiusura. –