¿Es posible tener una función PHP que sea tanto recursiva como anónima? Este es mi intento de hacerlo funcionar, pero no pasa el nombre de la función.
$factorial = function( $n ) use ( $factorial ) {
if( $n <= 1 ) return 1;
return $factorial( $n - 1 ) * $n;
};
print $factorial( 5 );
También soy consciente de que esta es una mala manera de implementar factorial, es solo un ejemplo.
global $factorial
?print $factorial( 0);
Respuestas:
Para que funcione, debe pasar $ factorial como referencia
fuente
&
es por valor. Todo con&
es por referencia. Los "objetos" no son valores en PHP5 y no pueden asignarse ni pasarse. Se trata de una variable cuyo valor es una referencia de objeto. Como todas las variables, se puede capturar por valor o por referencia, dependiendo de si hay un&
.$factorial
se cambiará antes de llamar a la función y puede resultar en un comportamiento extraño.Sé que esto podría no ser un enfoque simple, pero aprendí acerca de una técnica llamada "arreglo" de los lenguajes funcionales. La
fix
función de Haskell se conoce más generalmente como el combinador Y , que es uno de los combinadores de punto fijo más conocidos .Un punto fijo es un valor que no se modifica por una función: 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,...)
), escribirlas después de la función:f x y ...
. El combinador Y se define comoY f = f (Y f)
; o, con un solo argumento para la función recursed,Y f x = f (Y f) x
.Dado que PHP no curry automáticamente las funciones, es un poco complicado hacer el
fix
trabajo, pero creo que es interesante.Tenga en cuenta que esto es casi lo mismo que las soluciones de cierre simples que otros han publicado, pero la función
fix
crea el cierre por usted. Los combinadores de punto fijo son ligeramente 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.fuente
call_user_func_array()
es tan lento como la Navidad.call_user_func_array
.array_unshift( $args, fix($func) );
? Args ya está cargado con los parámetros, y la recursión real la realiza call_user_func_array (), entonces, ¿qué hace esa línea?Aunque no es para uso práctico, la extensión de nivel C mpyw-junks / phpext-callee proporciona una recursión anónima sin asignar variables .
fuente
En las versiones más recientes de PHP puedes hacer esto:
Esto puede conducir a un comportamiento extraño.
fuente
Puede usar Y Combinator en PHP 7.1+ como se muestra a continuación:
Juega con él: https://3v4l.org/7AUn2
Códigos fuente de: https://github.com/whitephp/the-little-phper/blob/master/src/chapter_9.php
fuente
Con una clase anónima (PHP 7+), sin definir una variable:
fuente