Ich habe F # gelernt und es beginnt zu beeinflussen, wie ich denke, wenn ich C # programmiere. Zu diesem Zweck habe ich die Rekursion verwendet, wenn ich der Meinung bin, dass das Ergebnis die Lesbarkeit verbessert, und ich kann mir nicht vorstellen, dass es zu einem Stapelüberlauf führt.
Dies führt mich zu der Frage, ob Compiler rekursive Funktionen automatisch in eine äquivalente nicht-rekursive Form konvertieren könnten oder nicht.
programming-languages
compiler
recursion
Aaron Anodide
quelle
quelle
return recursecall(args);
für die Rekursion, desto komplexer Sachen durch die Schaffung eines expliziten Stapel möglich ist und es auf kurvigen, aber ich bezweifle , werden sieAntworten:
Ja, einige Sprachen und Compliler konvertieren rekursive Logik in nicht rekursive Logik. Dies wird als Tail-Call-Optimierung bezeichnet. Beachten Sie, dass nicht alle rekursiven Aufrufe für die Tail-Call-Optimierung geeignet sind. In dieser Situation erkennt der Compiler eine Funktion der Form:
Hier kann die Sprache erkennen, dass das zurückgegebene Ergebnis das Ergebnis einer anderen Funktion ist, und einen Funktionsaufruf mit einem neuen Stapelrahmen in einen Sprung umwandeln.
Beachten Sie, dass die klassische Fakultätsmethode:
ist wegen der bei der rückgabe notwendigen inspektion nicht schwanzrufoptimierbar.
Um diesen Tail Call zu optimieren,
Kompilieren Sie diesen Code mit
gcc -O2 -S fact.c
(-O2 ist erforderlich, um die Optimierung im Compiler zu ermöglichen, aber mit mehr Optimierungen von -O3 wird es für einen Menschen schwer zu lesen ...)Man kann in dem Segment sehen
.L4
, diejne
eher als eincall
(das macht einen Subroutinen - Aufruf mit einem neuen Stapelrahmen).Beachten Sie, dass dies mit C durchgeführt wurde. Die Optimierung von Tail-Aufrufen in Java ist schwierig und hängt von der JVM-Implementierung ab. Tail-Recursion + Java und Tail-Recursion + Optimierung sind gute Tag-Sets zum Durchsuchen. Sie können andere JVM Sprachen sind in der Lage zu optimieren Endrekursion finden besser (try clojure (die die erfordert recur zu Endrekursion optimize) oder scala).
quelle
Vorsichtig auftreten.
Die Antwort lautet ja, aber nicht immer und nicht alle. Dies ist eine Technik, die unter ein paar verschiedenen Namen geführt wird, aber hier und auf Wikipedia finden Sie einige ziemlich eindeutige Informationen .
Ich bevorzuge den Namen "Tail Call Optimization", aber es gibt andere und einige Leute werden den Begriff verwirren.
Das heißt, es gibt ein paar wichtige Dinge zu realisieren:
Um einen Tail-Anruf zu optimieren, sind für den Tail-Anruf Parameter erforderlich, die zum Zeitpunkt des Anrufs bekannt sind. Das heißt, wenn einer der Parameter ein Aufruf der Funktion selbst ist, kann er nicht in eine Schleife konvertiert werden, da dies eine willkürliche Verschachtelung dieser Schleife erfordern würde, die zur Kompilierungszeit nicht erweitert werden kann.
C # optimiert Tail Calls nicht zuverlässig. Die IL verfügt über die Anweisung, die der F # -Compiler ausgibt, der C # -Compiler gibt sie jedoch inkonsistent aus. Abhängig von der JIT-Situation kann die JIT dies möglicherweise tun oder auch gar nicht. Sie sollten sich nicht darauf verlassen, dass Ihre Tail Calls in C # optimiert werden. Das Risiko eines Überlaufs ist dabei erheblich und real
quelle