Frage
Ich lerne R5RS Schema zur Zeit (von PocketScheme) und ich finde, dass ich eine Funktion nutzen könnten, die in einigen Varianten von Schema aufgebaut ist, aber nicht alle: anhängen
Mit anderen Worten -. Destruktiv eine Liste zu ändern
Ich bin nicht so sehr interessiert in dem eigentlichen Code als Antwort so viel wie den Prozess zu verstehen, mit denen man eine Liste als eine Funktion übergeben konnte (oder einen Vektor oder string) und mutiert es dann.
Beispiel:
(define (append! lst var)
(cons (lst var))
)
Wenn ich den Ansatz verwenden, wie oben, ich habe so etwas wie (define list (append! foo (bar))
zu tun, was ich etwas allgemeinere möchte.
Lösung
Mutation, obwohl erlaubt, ist stark in Schema abgeraten. PLT ging sogar so weit, set-car!
und set-cdr!
zu entfernen (obwohl sie „ersetzt“, um sie mit set-mcar!
und set-mcdr!
). Allerdings schien eine Spezifikation für append!
in SRFI-1 . Diese append!
ist ein wenig anders als deine. Im SRFI, die Umsetzung können , ist aber nicht erforderlich die Nachteile Zellen zu modifizieren, um die Listen anzuhängen.
Wenn Sie eine append!
haben wollen, das ist garantiert die Struktur der Liste zu ändern, die angehängt ist wird, werden Sie wahrscheinlich selbst, es zu schreiben. Es ist nicht schwer:
(define (my-append! a b)
(if (null? (cdr a))
(set-cdr! a b)
(my-append! (cdr a) b)))
Um die Definition einfach zu halten, gibt es keine Fehlerprüfung hier, aber es ist klar, dass Sie in einer Liste der Länge mindestens 1 als a
passieren müssen, und (vorzugsweise) eine Liste (beliebige Länge) als b
. Der Grund a
muss mindestens Länge 1 ist, weil Sie nicht auf eine leere Liste set-cdr!
kann.
Da Sie sind daran interessiert, wie das funktioniert, werde ich sehen, ob ich erklären kann. Im Grunde, was wir tun wollen ist die Liste a
geht nach unten, bis wir zum letzten cons
Paar bekommen, die (<last element> . null)
ist. So sehen wir zum ersten Mal, wenn a
ist bereits das letzte Element in der Liste von in den null
für cdr
überprüfen. Wenn es ist, verwenden set-cdr!
wir es auf die Liste setzen wir anhängen, und wir sind fertig. Wenn nicht, haben wir my-append!
auf der cdr
von a
zu nennen. Jedes Mal, wenn wir dies tun wir näher am Ende a
. Da dies eine Mutations-Operation ist, sind wir nichts geht zurück, so müssen wir nicht über Bildung unserer modifizierten Liste als Rückgabewert sorgen.
Andere Tipps
Besser spät als nie in ein paar Putting 2-3 Cent zu diesem Thema ...
(1) Es ist nichts falsch mit den destruktiven Verfahren in Schema mit , während gibt es einen einzigen Verweis auf die stucture modifizierte. So zum Beispiel, den Aufbau einer großen Liste effizient, Stück für Stück über eine einzige Referenz - und wenn Sie fertig sind, dass zu machen (jetzt vermutlich nicht-zu-sein-modifizierte) Liste bekannt und indirekten Verweisen auf verschiedenen referents
.(2) Ich denke, APPEND! sollte wie APPEND verhalten, nur (potentiell) destruktiv. Und so APPEND! erwartet eine beliebige Anzahl von Listen als Argumente sollte. Jede Liste, aber der letzte wäre vermutlich SET-CDR werden! 'D zum nächsten.
(3) Die obige Definition von APPEND! im Wesentlichen ist NCONC von Mac Lisp und Common Lisp. (Und andere lispelt).