eine Tail-Recursion-Version Liste anhängende Funktion

8

Ich sehe mehrere Beispiele für die Implementierung von append einem Element in eine Liste, aber alle verwenden keine Tail-Rekursion . Wie implementiert man eine solche Funktion in einem funktionalen Stil?

%Vor%     
象嘉道 06.11.2012, 16:55
quelle

5 Antworten

6

Das Folgende ist eine Implementierung der Optimierung von Tail-Recursion-Modulo-Contras , die zu einem vollständig rekursiven Tail-Code führt. Es kopiert die Eingabestruktur und fügt dann das neue Element durch Mutation top-down hinzu. Da diese Mutation mit ihren internen frisch erzeugten Daten gemacht wird, ist sie immer noch funktional (ändert nichts an Daten, die in sie hineingelangt sind und hat keine beobachtbaren Auswirkungen, außer dass sie ihr Ergebnis erzeugt):

%Vor%

Ich mag es, einen "Head-Sentinel" -Trick zu verwenden, der den Code erheblich vereinfacht, und zwar auf Kosten der Zuweisung von nur einer zusätzlichen Zelle.

Dieser Code verwendet Low-Level-Mutationsprimitive, um zu erreichen, was in einigen Sprachen (z. B. Prolog) automatisch von einem Compiler erledigt wird. In einem TRMC-optimierenden hypothetischen Schema könnten wir den folgenden tail-rekursiven Modulo-Cons -Code schreiben und einen Compiler automatisch in eine Entsprechung des obigen Codes übersetzen lassen:

%Vor%

Wenn nicht für die Operation cons , wäre append-elt . Hier kommt die TRMC-Optimierung ins Spiel.

    
Will Ness 06.11.2012 17:52
quelle
4

Nun ist möglich, eine tail-rekursive append-element Prozedur zu schreiben ...

%Vor%

... aber es ist ineffizienter mit dem reverse (in gutem Maße). Ich kann nicht an ein anderes funktionelles denken (z. B. ohne die Eingabeliste zu ändern), um diese Prozedur als Tail-Recursion zu schreiben, ohne die Liste zuerst umzukehren.

Für eine nicht funktionale Antwort auf die Frage lieferte @WillNess eine nette Schema-Lösung, die eine interne Liste mutierte.

    
Óscar López 06.11.2012 17:17
quelle
2

Sie können nicht naiv, aber sehen Sie auch Implementierungen, die TCMC - Tail Call Modulo Cons zur Verfügung stellen. Das erlaubt

%Vor%

tail-call TAIL-EXPR , wenn die Nachteile selbst ein Tail-Call ist.

    
LeoNerd 06.11.2012 18:12
quelle
2

Dies ist eine funktionale, tail rekursive append-elt mit Fortsetzungen:

%Vor%

In Sachen Leistung ist es Wills Mutation in Racket und Gambit sehr ähnlich, aber in Ikarus und Chicken Óscar lief es besser. Mutation war jedoch immer der beste Darsteller. Ich hätte das aber nicht benutzt, sondern eine leichte Version von Oscar's Eintrag, nur weil es einfacher zu lesen ist.

%Vor%

Und wenn Sie die Performance verändern möchten, hätte ich Folgendes getan:

%Vor%     
Sylwester 20.07.2013 21:38
quelle
1

Dies ist Lisp, nicht Schema, aber ich bin mir sicher, dass Sie übersetzen können:

%Vor%

Ich behalte den Kopf und den Schwanz der Rückgabeliste und modifiziere den Schwanz, während ich das Listenargument durchquere.

    
sds 06.11.2012 17:40
quelle