Mein aktuelles Verständnis von Rekursion ist, dass es sich jederzeit eine Methode nennt.
Das ist richtig. Rekursive Definitionen sind selbstverweisende Definitionen.
Zwei interessante Eigenschaften rekursiver Definitionen sind Produktivität und Terminierung. Ein Programm ist produktiv, wenn es weiterhin Ausgaben liefert, obwohl die volle Ausgabe niemals kommen kann (daher kann es nicht enden). Ein Programm wird beendet, wenn es seine volle Ausgabe in endlicher Zeit liefert.
Zum Beispiel ist dies ein produktives, nicht-Abschlussprogramm:
Naturals(int i) {
Console.WriteLine(i);
Naturals(i + 1);
}
Dies ist ein Abschlussprogramm:
UpToTen(int i) {
Console.WriteLine(i);
if (i < 10) UpToTen(i + 1);
}
Dies ist ein nicht-produktives Programm:
DoNothing() {
DoNothing();
}
Wenn Menu
Anrufe MenuError
und MenuError
Anrufe Menu
, wird dies manchmal gegenseitige Rekursion genannt. Der einzige Unterschied ist unsere Organisation; wir können den Code umschreiben, um nur eine Methode zu haben, indem wir MenuError
einreihen.
Menu() {
if (i < 2) {
Console.WriteLine();
}
else {
Console.WriteLine("Something Went Wrong!");
Console.WriteLine("Something went wrong!");
Menu();
}
}
Sie können in der Tat abstrakt Rekursion selbst:
// General definition
A Fix<A>(Func<Func<A>,A> f) {
return f(() => Fix(f));
}
// Special definition for void functions
void Fix(Action<Action> f) {
f(() => Fix(f));
}
void Menu(Action menu) {
if (i < 2) {
Console.WriteLine();
}
else {
Console.WriteLine("Something Went Wrong!");
Console.WriteLine("Something went wrong!");
menu();
}
}
Fix(Menu);
Hier ist ein weiteres Beispiel Fix
mit der Fakultäts-Funktion zu definieren.
Func<int, int> Fac(Func<Func<int, int>> fac) {
return i => i == 0 ? 1 : i * fac()(i - 1);
}
// Fix<Func<int, int>>(Fac) is the factorial function
Sie fragen sich vielleicht, warum Fix
die Signatur nicht A Fix<A>(Func<A,A> f)
stattdessen haben. Dies liegt daran, dass C# eine strikte Sprache ist, dh Argumente werden ausgewertet, bevor die Funktionsanwendung ausgewertet wird. Mit der einfacheren Signatur würde das C# -Programm in unendlicher Rekursion enden.
Ich weiß nicht, ob es als rekursiv oder nicht betrachtet wird. Aber ich weiß eine Sache, die definitiv in Betracht gezogen wird: [Reentrant] (https://en.wikipedia.org/wiki/Reentrancy_ (Computing)) (Eine Reentrant-Funktion ist eine Funktion, die ein zweites Mal vom selben Call-Stack aufgerufen wird bevor der erste Anruf abgeschlossen ist) –
Angenommen, ich habe eine Reihe von Methoden. Angenommen, ich zeichne eine gerichtete Kante von einer Methode zu einer anderen (möglicherweise selbst), wenn sie Code hat, um sie "aufzurufen" (angenommen, dass der gesamte Code erreichbar ist). Rekursion, in Bezug auf die Graphentheorie, ist immer dann, wenn es einen Zyklus gibt, selbst oder nicht. –
http://www.etymonline.com/index.php?term=recursion Wenn der gleiche Thread früher oder später "zurückfährt", um die von ihm ausgeführte Funktion aufzurufen, handelt es sich um eine Rekursion. Es gibt keinen konzeptionellen Unterschied zwischen Ihren Beispielen, der Punkt ist, dass sie die Funktion erneut aufruft, bevor sie von dem früheren Aufruf zurückkommt. –