Ein schlichter Aufruf ist ein Aufruf in Ergebnisposition.
Ein rekursiver Aufruf, der schlicht ist, heißt endrekursiv (engl.: tail recursive). Auch die Bezeichnung restrekursiv ist üblich.
Beispiele für schlichte Aufrufe
(setq odd* '(lambda (x) (cond ((zerop x) nil) (t (even* (sub1 x))) ) ) ) (setq even* '(lambda (x) (cond ((zerop x)) (t (odd* (sub1 x))) ) ) )
In diesem Beispiel liegt verschränkte Rekursion vor. Der Aufruf von even* in der Funktion odd* ist ein schlichter Aufruf. In gleicher Weise ist auch der Aufruf von odd* in der Funktion even* ein schlichter Aufruf.
Beispiel einer endrekursiven Definition:
(setq last* '(lambda (x) (cond ((null (cdr x)) x) (t (last* (cdr x))) ) ) )
In dieser Funktion wird ein rekursiver Aufruf von last* als schlichter Aufruf verwendet.
(setq sum '(lambda (i0 in fn) ((label compute-sum (lambda (s i) (cond ((greaterp i in) s) (t (compute-sum (plus s (fn i)) (add1 i))) ) ) ) 0 i0 ) ) )
Die lokal vereinbarte Funktion compute-sum enthält einen endrekursiven Aufruf.
Hier müssen die Argumentwerte des rekursiven Aufrufs noch in der vom Lambda-Ausdruck erzeugten Umgebung ausgewertet werden. Der rekursive Aufruf selbst kann dann die nicht mehr benötigten Bindings aufgeben, bevor er neue Bindings erzeugt.
Ein allgemeinerer Fall verschränkter Rekursion:
(setq p1 '(lambda (x y ) % soll z verwenden (cond ((zerop x) nil) (t (p2 (sub1 x))) ) ) ) (setq p2 % soll y verwenden '(lambda (x z) (cond ((zerop x)) (t (p1 (sub1 x))) ) ) )
Es ist im Augenblick nicht klar, wie hier das Anwachsen des Lisp-Kellers vermieden werden kann.
...