Verstehen von Y Combinator durch generische Lambdas
eim Aufbau einer kleinen Lambda-basierten Metaprogramm-Bibliothek musste ich in einem generischen C ++ 14-Lambda eine Rekursion verwenden, um ein @ zu implementiere left-fold.
Meine eigene Lösung hat das Lambda selbst als einen seiner Parameter übergeben, wie folgt:
template <typename TAcc, typename TF, typename... Ts>
constexpr auto fold_l_impl(TAcc acc, TF f, Ts... xs)
{
// Folding step.
auto step([=](auto self)
{
return [=](auto y_acc, auto y_x, auto... y_xs)
{
// Compute next folding step.
auto next(f(y_acc, y_x));
// Recurse if required.
return static_if(not_empty(y_xs...))
.then([=]
{
// Recursive case.
return self(self)(next, y_xs...);
})
.else_([=]
{
// Base case.
return next;
})();
};
});
// Start the left-fold.
return step(step)(acc, xs...);
}
step
ist das "Haupt" -Lambda, das die Rekursion startet. Es wird eine Funktion mit der gewünschten linken Signatur @ zurückgegebe (Akku, aktueller Artikel, verbleibende Artikel ...).
Die Funktion ruft sich rekursiv mit @ aself(self)(next, y_xs...)
.
Ich bin vor kurzem auf @ gestoßdieser Vorschla das ein @ hinzufügen möchY Combinator zur Standardbibliothek, und nachdem ich es gelesen habe, scheint es sehr ähnlich zu dem zu sein, was ich hier mache.
Leider "klickt" das Konzept des Y-Kombinators immer noch nicht für mich - mir fehlt etwas und ich kann mir nicht vorstellen, wie ich das, was ich mit dem @ gemacht habe, verallgemeinern solself
-Parameter für jede Funktion unter Vermeidung desstep
Boilerplate.
Ich habe gelesendiese ausgezeichnete StackOverflow-Antwort in Bezug auf die Sache, aber es hat immer noch nicht für mich "klicken".
(Aus dieser Antwort) Eine rekursive Fakultät wird folgendermaßen definiert:
fact =
(recurs) =>
(x) =>
x == 0 ? 1 : x * recurs(x - 1);
Dasrecurs
-Parameter scheint die gleiche Rolle zu haben wie meinself
Parameter. Was ich nicht verstehe ist wierecurs
wird aufgerufen, ohne @ zu übergebrecurs
wieder in sich.
Ich muss @ anrufself
so was:self(self)(params...)
.
recurs
heißt jedoch wierecurs(params...)
.
Versuch, @ anzurufself(params...)
führt zu einem Compilerfehler, der mich darüber informiert, dassself
benötigt nur einen einzigen Parameter (welches ist dasauto self
Lambda-Parameter).
Was fehle ich hier? Wie könnte ich mein @ umschreibfold_l_impl
Lambda so, dass seine Rekursion durch die Verwendung eines Y-Kombinators verallgemeinert werden kann?