Je sais que ce ne serait pas une approche simple, mais j'ai appris une technique appelée "fix" de langages fonctionnels. L' fix
fonction de Haskell est connu plus généralement sous forme de Y combinator, qui est l'un des plus connus de point fixe combinators.
Un point fixe est une valeur qui est inchangé par une fonction: d'un point fixe d'une fonction f est tout x tel que x = f(x). Un combinateur de point fixe o est une fonction qui retourne un point fixe pour toute fonction f. Étant donné que y(f) est un point fixe de f, nous avons y(f) = f(y(f)).
Essentiellement, le Y combinator crée une nouvelle fonction qui prend en compte tous les arguments de l'original, plus un argument supplémentaire qui est la fonction récursive. Comment cela fonctionne est le plus évident à l'aide de la notation. Au lieu d'écrire des arguments entre parenthèses (f(x,y,...)
), les écrire après la fonction: f x y ...
. Le Y combinator est défini comme Y f = f (Y f)
; ou, avec un seul argument pour la recursed fonction, Y f x = f (Y f) x
.
Depuis PHP n'est pas automatiquement curry fonctions, c'est un peu un hack pour faire fix
de travail, 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 );
Remarque c'est presque la même que la simple fermeture des solutions publiés par d'autres, mais la fonction fix
crée la fermeture pour vous. Point fixe combinators sont légèrement plus complexe que l'utilisation d'une fermeture, mais sont plus générales, et avoir d'autres usages. Alors que la méthode de fermeture est plus approprié pour PHP (ce qui n'est pas vraiment un langage fonctionnel), le problème d'origine est un exercice que pour la production, et donc le Y combinator est une approche viable.