Die Definition eines Y-Kombinators in F # lautet
let rec y f x = f (y f) x
Als erstes Argument erwartet f eine Fortsetzung der rekursiven Teilprobleme. Wenn wir das yf als Fortsetzung verwenden, sehen wir, dass f auf aufeinander folgende Aufrufe angewendet wird, sobald wir uns entwickeln können
let y f x = f (y f) x = f (f (y f)) x = f (f (f (y f))) x etc...
Das Problem ist, dass dieses Schema a priori die Verwendung von Tail-Call-Optimierungen ausschließt: In der Tat könnte eine Operation in den fs anstehen. In diesem Fall können wir den lokalen Stapelrahmen, der mit f assoziiert ist, nicht einfach mutieren.
So :
- Zum einen erfordert die Verwendung des Y-Kombinators eine explizit andere Fortsetzung als die eigentliche Funktion.
- Wenn Sie TCO anwenden möchten, möchten wir, dass in f keine Operation ansteht und nur f selbst aufgerufen wird.
Kennen Sie eine Möglichkeit, diese beiden zu versöhnen? Wie ein Y mit Akkumulator-Trick oder ein Y mit CPS-Trick? Oder ein Argument, das beweist, dass es unmöglich ist, es zu tun?
f
. Wir können sehen, dass y
das f
mit einem Thunk klappen könnte (y f)
, aber wie Sie sagen, f
könnte eine Operation anstehen. Ich denke, es wäre interessant zu wissen, ob es einen separaten Kombinator gibt, der die Rückrufe erleichtert. Ich frage mich, ob diese Frage auf der CS Stackexchange-Website mehr Beachtung finden würde.