Mówiąc prosto, rekurencja ogona jest rekurencją, w której kompilator może zastąpić wywołanie rekurencyjne poleceniem „goto”, więc skompilowana wersja nie będzie musiała zwiększać głębokości stosu.
Czasami zaprojektowanie funkcji rekurencyjnej ogona wymaga utworzenia funkcji pomocniczej z dodatkowymi parametrami.
Na przykład nie jest to funkcja rekurencyjna:
int factorial(int x) {
if (x > 0) {
return x * factorial(x - 1);
}
return 1;
}
Ale jest to funkcja rekurencyjna:
int factorial(int x) {
return tailfactorial(x, 1);
}
int tailfactorial(int x, int multiplier) {
if (x > 0) {
return tailfactorial(x - 1, x * multiplier);
}
return multiplier;
}
ponieważ kompilator może przepisać funkcję rekurencyjną na nierekurencyjną, używając czegoś takiego (pseudokod):
int tailfactorial(int x, int multiplier) {
start:
if (x > 0) {
multiplier = x * multiplier;
x--;
goto start;
}
return multiplier;
}
Reguła kompilatora jest bardzo prosta: gdy znajdziesz „ return thisfunction(newparameters);
”, zamień go na „ parameters = newparameters; goto start;
”. Można to jednak zrobić tylko wtedy, gdy wartość zwrócona przez wywołanie rekurencyjne zostanie zwrócona bezpośrednio.
Jeśli wszystkie wywołania rekurencyjne w funkcji można zastąpić w ten sposób, jest to funkcja rekurencyjna.