In der funktionalen Programmierung werden Funktionen vielfach rekursiv definiert. Rekursion allerdings verursacht im Allgemeinen einen hohen Verwaltungsaufwand, da jeder rekursive Aufruf einen neuen Eintrag im Aufrufstack erzeugt. In vielen Fällen, wenn die Rekursionstiefe zu groß wird, kommt es sogar zu einem Überlauf des Stacks (engl.: stack overflow).
Bei der sogenannten Endrekursion (engl.: tail recursion) dagegen kann der jeweils letzte Eintrag im Aufrufstack wiederverwendet werden, da er nicht mehr benötigt wird. Ein Überlauf des Stacks ist somit nicht möglich.
Mithilfe eines Iterationsschemas lassen sich einerseits Programmschleifen, andererseits aber auch endrekursive Funktionen entwerfen.
Eine andere Möglichkeit, die sich in bestimmten Fällen anwenden lässt, ist die formale Umwandlung einer rekursiven Funktion in eine entsprechende endrekursive Funktion. Dieses Verfahren wird im Folgenden in der funktionalen Programmiersprache Haskell anhand von Beispielen dargestellt.
Gegeben ist eine rekursive Haskell-Funktion der folgenden Form
Hierbei ist der Funktionswert ein Element eines Monoids mit der Verknüpfung o, d.h. die Funktion o ist assoziativ, und das Element e ist das neutrale Element.
Der Ausdruck h x bildet das Rekursionsende, wenn die Bedingung b x eintritt. Ansonsten wird die Funktion f mit dem Argument k x rekursiv aufgerufen und mit i x verknüpft.
Diese Funktion f wird in eine endrekursive Version f ' wie folgt umgewandelt. Endrekursion ist in der funktionalen Programmierung die Entsprechung zu Iteration. Daher ist die hier verwendete Hilfsfunktion mit iterate bezeichnet.
Als erstes Beispiel betrachten wir die Fakultätsfunktion. Der Funktionswert ist ein Element aus dem Monoid (ℕ0, ·, 1).
Hierbei gelten die Entsprechungen
Dies führt zu folgender endrekursiven Version:
Als weiteres Beispiel betrachten wir die Funktion len zur Bestimmung der Länge einer Liste. Der Funktionswert ist ein Element aus dem Monoid (ℕ0, +, 0).
Hierbei gelten die Entsprechungen
Dies führt zu folgender endrekursiven Version:
Aufgabe 1: Überführen Sie die folgende rekursive Funktion zum Aufsummieren einer Liste von Zahlen in eine entsprechende endrekursive Version.
Lösung:
Es gelten die Entsprechungen
Dies führt zu folgender endrekursiven Version: