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?

Antworten auf die Frage(2)

Ihre Antwort auf die Frage