Sé que esto podría no ser un enfoque simple, pero he aprendido acerca de una técnica llamada "fix" de los lenguajes funcionales. La función fix
de Haskell se conoce generalmente como Y combinator, que es una de las más conocidas fixed point combinators.
un punto fijo es un valor que no se ha modificado por una función de: un punto fijo de una función f es cualquier x tal que x = f (x). Un combinador de punto fijo y es una función que devuelve un punto fijo para cualquier función f. Como y (f) es un punto fijo de f, tenemos y (f) = f (y (f)).
Esencialmente, el combinador Y crea una nueva función que toma todos los argumentos del original, más un argumento adicional que es la función recursiva. Cómo funciona esto es más obvio usando la notación al curry. En lugar de escribir argumentos entre paréntesis (f(x,y,...)
), escríbalos después de la función: f x y ...
. El combinador Y se define como Y f = f (Y f)
; o, con un único argumento para la función recursada, Y f x = f (Y f) x
.
Dado que PHP no funciona automáticamente con curry, es un poco complicado hacer fix
, pero creo que es interesante.
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 esto es casi lo mismo que las soluciones de cierre simples otros han publicado, pero la función fix
crea el cierre para usted. Los combinadores de punto fijo son un poco más complejos que usar un cierre, pero son más generales y tienen otros usos. Si bien el método de cierre es más adecuado para PHP (que no es un lenguaje terriblemente funcional), el problema original es más un ejercicio que para la producción, por lo que el combinador Y es un enfoque viable.
No tengo PHP 5.3.0 para verificar, pero ¿intentó usar 'global $ factorial'? – kennytm
* (nota al margen) * a Lamba es una función anónima, mientras que la anterior es un Cierre. – Gordon
Lambdas y Closures no son mutuamente excluyentes. De hecho, algunas personas creen que un cierre tiene que ser lambda para que sea un cierre (función anónima). Por ejemplo, Python tiene que darle un nombre a la función primero (dependiendo de la versión).Porque tiene que darle un nombre que no puede alinear y algunos dirán que lo descalifica para que no sea un cierre. –