Мое нынешнее понимание рекурсии заключается в том, что это когда-либо вызов метода .
Это правильно. Рекурсивные определения являются определениями самореференции.
Два интересных свойства рекурсивных определений: Производительность и Прекращение. Программа продуктивна, если она по-прежнему дает выход, хотя полная выходная мощность может никогда не появиться (следовательно, она не может завершиться). Программа завершается, если она дает полный выход за конечное время.
Например, это продуктивно, не-терминатор программа:
Naturals(int i) {
Console.WriteLine(i);
Naturals(i + 1);
}
Это программа терминатор:
UpToTen(int i) {
Console.WriteLine(i);
if (i < 10) UpToTen(i + 1);
}
Это непродуктивный программа:
DoNothing() {
DoNothing();
}
Если Menu
звонки MenuError
и MenuError
звонки Menu
, это иногда называют взаимной рекурсии. Единственная разница - наша организация; мы можем переписать код, чтобы иметь только один метод, введя в таблицу MenuError
.
Menu() {
if (i < 2) {
Console.WriteLine();
}
else {
Console.WriteLine("Something Went Wrong!");
Console.WriteLine("Something went wrong!");
Menu();
}
}
Вы можете на самом деле абстрактная рекурсия сами:
// 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);
Вот другой пример использования Fix
определить функцию факториала.
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
Вы можете задаться вопросом, почему Fix
не имеет подписи A Fix<A>(Func<A,A> f)
вместо этого. Это связано с тем, что C# является строгим языком, что означает, что он оценивает аргументы, прежде чем оценивать приложение функции. С более простой сигнатурой программа C# закончится бесконечной рекурсией.
Я не знаю, считается ли это рекурсивным или нет. Но я знаю одну вещь, которая определенно считается: [Reentrant] (https://en.wikipedia.org/wiki/Reentrancy_ (вычисления)) (Функция повторного входа - это функция, которая получает второй вызов по тому же стеку вызовов до завершения первого вызова) –
Предположим, у меня есть набор методов. Предположим, что я рисую направленное ребро от одного метода к другому (возможно, самому себе), если у него есть код, чтобы «вызвать» его (предположим, что весь код доступен). Рекурсия, в терминах теории графов, - это когда-либо есть цикл, я или иначе. –
http://www.etymonline.com/index.php?term=recursion Если тот же самый поток «убежит» рано или поздно, чтобы вызвать выполняемую им функцию, это рекурсия. Между вашими примерами нет принципиальной разницы, дело в том, что он снова вызывает функцию, прежде чем она вернется с предыдущего вызова. –