Iteracyjna rekurencja ogona jest ogólnie realizowana za pomocą Tail calls. Jest to w zasadzie transformacja wywołania rekursywnego do prostej pętli.
C# przykład:
uint FactorialAccum(uint n, uint accum) {
if(n < 2) return accum;
return FactorialAccum(n - 1, n * accum);
};
uint Factorial(uint n) {
return FactorialAccum(n, 1);
};
do
uint FactorialAccum(uint n, uint accum) {
start:
if(n < 2) return accum;
accum *= n;
n -= 1;
goto start;
};
uint Factorial(uint n) {
return FactorialAccum(n, 1);
};
lub jeszcze lepiej:
uint Factorial(uint n) {
uint accum = 1;
start:
if(n < 2) return accum;
accum *= n;
n -= 1;
goto start;
};
C nie # rzeczywistym ogon rekursji tym, że wartość powrotna jest modyfikowany większość kompilatorów nie złamie tego WN pętlę:
int Power(int number, uint power) {
if(power == 0) return 1;
if(power == 1) return number;
return number * Power(number, --power);
}
do
int Power(int number, uint power) {
int result = number;
start:
if(power == 0) return 1;
if(power == 1) return number;
result *= number;
power--;
goto start;
}
Twoja pierwsza funkcja nie jest ogon rekurencyjnej , więc to nie zmieni się w iterację w Erlangu. – Jules
Masz zasadniczo rację, ale dobry kompilator powinien być w stanie zobaczyć strukturę. Zmienię mój przykład później. – Dykam
+ Należy pamiętać, że ostatnie dwie akcje poprzedzające skok powrotny są bezpośrednio wyprowadzane z ogona. – Dykam