Ich halte Strukturen für effektiv veraltet, daher verwende ich sie überhaupt nicht.
Wenn ich einen festen Satz bekannter Schlüssel habe, die in vielen Karteninstanzen verwendet werden, erstelle ich normalerweise einen Datensatz. Die großen Vorteile sind:
- Performance
- Die generierte Klasse hat einen Typ, den ich in Multimethoden oder anderen Situationen einschalten kann
- Mit zusätzlichen Makromaschinen rund um Defrecord kann ich Feldvalidierung, Standardwerte und alles andere, was ich will, abrufen
- Datensätze können beliebige Schnittstellen oder Protokolle implementieren (Karten können nicht)
- Aufzeichnungen dienen für die meisten Zwecke als Karten
- Die Rückgabe von Schlüsseln und Werten führt zu einer stabilen Reihenfolge (pro Erstellung)
Einige Nachteile von Aufzeichnungen:
- Da Datensätze Java-Klasseninstanzen sind (keine Clojure-Maps), gibt es keine strukturelle Freigabe, sodass dieselbe Datensatzstruktur wahrscheinlich mehr Speicher benötigt als die entsprechende Map-Struktur, die geändert wurde. Es gibt auch mehr Objekterstellung / -zerstörung, wenn Sie einen Datensatz "ändern", obwohl die JVM speziell dafür entwickelt wurde, diese Art von kurzlebigem Müll zu essen, ohne ins Schwitzen zu geraten.
- Wenn Sie während der Entwicklung Datensätze ändern, müssen Sie Ihre REPL wahrscheinlich häufiger neu starten, um diese Änderungen zu übernehmen. Dies ist normalerweise nur bei engen Entwicklungsabschnitten ein Problem.
- Viele vorhandene Bibliotheken wurden nicht aktualisiert, um Datensätze zu unterstützen (Postwalk, Zip, Matchure usw. usw.). Wir haben diese Unterstützung nach Bedarf hinzugefügt.
defstruct
. Siehe lispworks.com/documentation/HyperSpec/Body/… .Stuart Sierra hat kürzlich einen interessanten Artikel über "Lösen des Ausdrucksproblems mit Clojure 1.2" geschrieben, der auch einen Abschnitt über Folgendes enthält
defrecord
:http://www.ibm.com/developerworks/java/library/j-clojure-protocols/index.html#datatypes
Ich denke, der gesamte Artikel ist ein guter Ausgangspunkt für das Verständnis von Protokollen und Aufzeichnungen.
quelle
Ein weiterer großer Vorteil ist, dass der Datensatz einen Typ (seine Klasse) hat, von dem Sie versenden können.
Ein Beispiel, das diese Funktion verwendet, aber nicht für alle Verwendungsmöglichkeiten repräsentativ ist, ist das folgende:
(defprotocol communicate (verbalize [this])) (defrecord Cat [hunger-level] communicate (verbalize [this] (apply str (interpose " " (repeat hunger-level "meow"))))) (defrecord Dog [mood] communicate (verbalize [this] (case mood :happy "woof" "arf"))) (verbalize (->Cat 3)) ; => "meow meow meow" (verbalize (->Dog :happy)) ; => "woof"
quelle
Verwenden Sie in den meisten Fällen Karten und Datensätze nur, wenn Sie Polymorphismus benötigen. Nur mit Karten können Sie immer noch Multimethoden verwenden. Sie benötigen jedoch Datensätze, wenn Sie Protokolle wünschen. Warten Sie daher, bis Sie Protokolle benötigen, bevor Sie auf Datensätze zurückgreifen. Vermeiden Sie sie bis dahin zugunsten eines datenzentrierteren und einfacheren Codes.
quelle
Zusätzlich zu dem, was zuvor erwähnt wurde, sind Datensätze nicht nur in Bezug auf die Leistung im Allgemeinen gleich oder überlegen und bieten dieselbe Programmierschnittstelle wie eine Karte, sondern auch eine milde Struktur: Schlüsselnamen und die Anzahl der Schlüssel werden zum Zeitpunkt von erzwungen Definition. Dies kann nützlich sein, um dumme Fehler zu vermeiden, bei denen von vielen Werten dieselbe Struktur erwartet wird (oder ansonsten nur künstlich starr).
Unabhängig von den ursprünglichen Motivationen unterscheidet sich auch diese Eigenschaft von Karten.
quelle