Eine einfache Append-Funktion wie diese (in F #):
%Vor%stürzt ab, wenn s groß wird, da die Funktion nicht tail rekursiv ist. Ich habe bemerkt, dass F # 's Standard Append-Funktion nicht mit großen Listen abstürzt, also muss es anders implementiert werden. Also fragte ich mich: Wie sieht eine rekursive Definition von Append aus? Ich habe mir so etwas ausgedacht:
%Vor%das funktioniert, sieht aber eher komisch aus. Gibt es eine elegantere Definition?
Traditionell (nicht tail-rekursiv)
%Vor%Mit einem Akkumulator (tail-recursive)
%Vor%Mit Fortsetzungen (tail-recursive)
%Vor%Es ist ziemlich einfach, jede nicht-tail rekursive Funktion in rekursive mit Fortsetzungen zu konvertieren, aber ich persönlich bevorzuge Akkus für einfache Lesbarkeit.
Zusätzlich zu dem, was Julia gepostet hat:
Verwenden von Sequenzausdrücken
Intern erzeugen Sequenzausdrücke tail-rekursiven Code, was gut funktioniert.
Verwenden von veränderbaren .NET-Typen
David erwähnte, dass F # -Listen mutiert werden können - dies ist jedoch nur auf F # -Kernbibliotheken beschränkt (und die Funktion kann nicht von Benutzern verwendet werden, da sie die funktionalen Konzepte durchbricht). Sie können veränderbare .NET-Datentypen verwenden, um eine auf Mutationen basierende Version zu implementieren:
Dies kann in einigen Szenarien nützlich sein, aber ich würde generell Mutationen im F # -Code vermeiden.
Aus einem kurzen Blick auf die F # -Quellen scheint der Schwanz innerlich veränderbar zu sein. Eine einfache Lösung wäre, die erste Liste umzukehren, bevor ihre Elemente in die zweite Liste eingefügt werden. Das, zusammen mit der Umkehrung der Liste, ist trivial, Schwanz rekursiv zu implementieren.
Tags und Links f# append tail-recursion