Un Y combinator est un "fonctionnelle" (une fonction qui fonctionne sur d'autres fonctions) qui permet la récursivité, lorsque vous ne pouvez pas se référer à la fonction à partir de l'intérieur de lui-même. Dans la théorie des sciences, il généralise la récursivité, l'abstraction de sa mise en œuvre, et ce qui le sépare du travail réel de la fonction en question. L'avantage de ne pas avoir besoin d'un moment de la compilation du nom de la fonction récursive est une sorte de bonus. =)
Ceci est applicable dans les langues qui prennent en charge les lambda fonctions. L' expressionde la lambdas signifie généralement qu'ils ne peuvent pas se référer à eux-mêmes par leur nom. Et de travail autour de ce en déclarant la variable, qui est venu à elle, puis à attribuer le lambda, pour compléter l'auto-référence de la boucle, est fragile. Le lambda variable peut être copié, et la variable d'origine attribué à nouveau, ce qui rompt l'auto-référence.
Y-combinators sont lourdes à mettre en œuvre, et souvent à l'utilisation en statique de type de langues ( langues procédurales sont souvent), parce que d'habitude de taper des restrictions exigent le nombre d'arguments de la fonction en question à être connu au moment de la compilation. Cela signifie qu'un y combinator doit être écrit pour tout argument compter que l'on doit utiliser.
Ci-dessous est un exemple de la façon dont l'utilisation et le fonctionnement d'un Y-Combinator, en C#.
À l'aide d'un Y-combinator implique un "inhabituel" la construction d'une fonction récursive. D'abord, vous devez écrire votre fonction comme un morceau de code qui appelle une pré-existante de la fonction, plutôt que de lui-même:
// Factorial, if func does the same thing as this bit of code...
x == 0 ? 1: x * func(x - 1);
Ensuite, vous transformer en une fonction qui prend une fonction à appeler, et retourne une fonction qui le fait. Cela s'appelle fonctionnel, car il faut une fonction, et effectue une opération avec elle que les résultats dans une autre fonction.
// A function that creates a factorial, but only if you pass in
// a function that does what the inner function is doing.
Func<Func<Double, Double>, Func<Double, Double>> fact =
(recurs) =>
(x) =>
x == 0 ? 1 : x * recurs(x - 1);
Maintenant, vous avez une fonction qui prend une fonction, et retourne une fonction qui donne l'impression d'être une factorielle, mais au lieu d'appeler lui-même, il appelle l'argument passé à la fonction externe. Comment voulez-vous faire de cette factoriel? Passer à la fonction interne à lui-même. Le Y Combinator fait que, en étant une fonction avec un nom définitif, ce qui peut introduire de la récursivité.
// One-argument Y-Combinator.
public static Func<T, TResult> Y<T, TResult>(Func<Func<T, TResult>, Func<T, TResult>> F)
{
return
t => // A function that...
F( // Calls the factorial creator, passing in...
Y(F) // The result of this same Y-combinator function call...
// (Here is where the recursion is introduced.)
)
(t); // And passes the argument into the work function.
}
Plutôt que de la factorielle d'appel lui-même, ce qui se passe, c'est que la factorielle appelle la factorielle générateur (retourné par l'appel récursif à Y Combinator). Et en fonction de la valeur actuelle de t la fonction renvoyée à partir du générateur d'appeler le générateur encore, à t - 1, ou juste de retour de 1, la résiliation de la récursivité.
C'est complexe et énigmatique, mais tout s'équilibrera au moment de l'exécution, et la clé de son travail est "l'exécution différée", et la rupture de la récursivité à durée de deux fonctions. L'intérieur F est passé comme argument, pour être appelé dans la prochaine itération, seulement si nécessaire.