Je sais que ce n'est peut-être pas une approche simple, mais j'ai appris une technique appelée «correction» à partir de langages fonctionnels. La fix
fonction de Haskell est plus généralement connue sous le nom de combinateur Y , qui est l'un des combinateurs à point fixe les plus connus .
Un point fixe est une valeur inchangée par une fonction: un point fixe d'une fonction f est tout x tel que x = f (x). Un combinateur à point fixe y est une fonction qui renvoie un point fixe pour toute fonction f. Puisque y (f) est un point fixe de f, nous avons y (f) = f (y (f)).
Essentiellement, le combinateur Y crée une nouvelle fonction qui prend tous les arguments de l'original, plus un argument supplémentaire qui est la fonction récursive. Comment cela fonctionne est plus évident en utilisant la notation au curry. Au lieu d'écrire des arguments entre parenthèses ( f(x,y,...)
), les écrire après la fonction: f x y ...
. Le combinateur Y est défini comme Y f = f (Y f)
; ou, avec un seul argument pour la fonction récursive,Y f x = f (Y f) x
.
Depuis PHP ne curry pas automatiquement les fonctions, c'est un peu un hack pour faire fix
fonctionner, mais je pense que c'est intéressant.
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 );
Notez que c'est presque la même chose que les solutions de fermeture simples que d'autres ont publiées, mais la fonction fix
crée la fermeture pour vous. Les combinateurs à virgule fixe sont légèrement plus complexes que l'utilisation d'une fermeture, mais sont plus généraux et ont d'autres utilisations. Alors que la méthode de fermeture convient mieux à PHP (qui n'est pas un langage terriblement fonctionnel), le problème d'origine est plus un exercice que pour la production, donc le combinateur Y est une approche viable.
global $factorial
?