die Y Combinator eines der interessantesten Phänomene in dem Lambda-Kalkül ist. Ich bezweifle, dass man sofort eine Interpretation seiner Funktionalität entwickeln kann.
Y = f => (g => g(g))(g => n => f(g(g))(n));
Lassen Sie uns versuchen, die Ableitung Schritt für Schritt zu verstehen. Ich werde die Pfeilfunktionen verwenden. Wenn Sie sich nicht damit auskennen, folgen Sie bitte this link. Sie sind sehr einfach. x => x
bedeutet function(x){return x;}
. Das Schlüsselwort JS this
hat eine andere Bedeutung innerhalb der Pfeile, aber das Thema ist nicht Thema.
Also werden wir immer mit der faktoriellen Funktion gehen, aber der Y-Kombinator, den wir ableiten werden, wird für alle rekursiven Funktionen gültig sein.
A Fakultäts-Funktion kann einfach ausgedrückt werden als
var fa = n => n === 0 ? 1 : n*fa(n-1);
fact(5) // <- 120
folgt aber sagen, dass wir nicht rekursiv auf die fa
Funktion beziehen möchten; stattdessen möchten wir eine funktionierende faktorielle Funktion aus einer hypothetischen Version der faktoriellen Funktion ableiten. Was ist eine hypothetische faktorielle Funktion? Die hypothetische faktorielle Funktion nimmt eine korrekte faktorielle Funktion an und gibt uns eine funktionierende faktorielle Funktion zurück. Wie die folgenden
var fh = f => n => n === 0 ? 1 : n*f(n-1);
Also, wenn ich pass fa
Funktion fh
als Argument wird es funktionieren. Mögen;
fh(fa)(5); // <- 120
Aber wir wollen nicht wie fa
auf eine andere Fakultätsfunktion beziehen, da wir bereits „Art“ definiert haben die Fakultät Logik innerhalb der fh
Funktion. Dann denken wir. fh
hält das f
Argument in Schließung und gibt mir eine funktionierende faktorielle Funktion zurück (n => n === 0 ? 1 : n*f(n-1)
), wenn ich eine richtige Fakultät Funktion wie fa
übergeben. Was ist, wenn ich mich ihm hingebe? Ein kurzer Versuch fh(fh)(5) // <- NaN
meh ..!
Also fangen wir an, mit der inneren Funktion zu spielen. Normalerweise würde ich diesen Schritt bestehen, aber es könnte hilfreich sein, die Transformationen zu sehen ... also lass uns fortfahren. Ich kann die fb
Funktion definieren Sie mir eine Funktion zurück, die zwei Argumente übernimmt, sich und Fakultäts Zählung n
fb = (f,n) => n === 0 ? 1 : n* f(f,n-1), // fb(fb,5) <- 120
So weit so gut, aber die zwei Argument Fakultäts-Funktion ist nicht in dem nahe, was ich suche. Ich kann sie trennen, indem ich einen weiteren funktionalen Schritt hinzufüge.
fc = f => n => n === 0 ? 1 : n* f(f)(n-1), // fc(fc)(5) <- 120
Nun ist dies ganz in der Nähe unserer hypothetischen Funktion fh
. Aber das Innere zeigt f(f)(n-1)
Wir müssen dies korrigieren, um f (n-1) zu zeigen. Nun können wir eine JS Schönheit IIFE verwenden, um uns zu helfen ...
Können Sie die IIFE ..? ((g,n) => n === 0 ? 1 : n * g(n-1))(f(f),n)
Obwohl dies in Ordnung scheint, muss ich das Doppelargument (g,n)
IIFE loswerden, um das gewünschte Ergebnis zu erzielen. Dies wird eine andere Ebene der Funktionsfähigkeit nehmen.
fe => f => n => (g => n => n === 0 ? 1 : n * g(n-1))(f(f))(n) // fe(fe)(5) <- 120
Jetzt haben wir innerhalb g => n => n === 0 ? 1 : n * g(n-1)
, die der Körper unserer hypothetischen Funktion fh
ist. Was bedeutet, ich kann ersetzen (ich liebe diesen Teil .. genau wie Kalkül Substitution; in der Tat ist es ...) fh
in der obigen Funktion zu lesen wie;
fe => f => n => fh(f(f))(n) // fe(fe)(5) <- 120
Ok Zeit, um es zu wickeln. Was ich in erster Linie wollte ..? Ich möchte fh
zu einer Funktion (Y-Kombinator) füttern und es ist Fixpunkt. Hier weiß ich, dass fe(fe)
fh
verwendet und mir die richtig funktionierende faktorielle Funktion zurückgibt. Lassen Sie uns also eine Funktion definieren, die unsere hypothetische rekursive Funktion als Argument annimmt und uns etwas funktioniert (behoben). IIFE, um wieder zu helfen.
Y = f => (g => g(g))(g => n => f(g(g))(n));
Also sollte dies für alles funktionieren. Versuchen wir unseren Y-Kombinator mit einer hypothetischen Fibonacci-Funktion.
var Y = f => (g => g(g))(g => n => f(g(g))(n)),
fibH = f => n => n === 0 ? 0
: n === 1 ? 1
: f(n-2) + f(n-1),
fibo = Y(fibH);
console.log(fibo(10));
Ich hoffe, es ist klar, ...
Vielleicht [diese] (http://stackoverflow.com/a/13759513/1048572) hilft? – Bergi
Die unendliche Rekursion ist faul. Die Funktion wird nicht immer aufgerufen, sie wird einfach wiederholt übergeben (und im Basisfall von "faktoriell" wird sie nicht mehr verwendet) – Bergi
Danke @Bergi Ich habe es mit deiner Hilfe herausgefunden. Am Punkt von 'Y (F)' ist die rekursive Struktur 'x (x)' nur eine Referenz, die als gebundene Variable 'faktoriell' innerhalb der 'Faktor'-Funktion übergeben und gespeichert wird, sie wird nicht aufgerufen dieser Punkt. –