2017-10-16 4 views
2

Wie kann ich einen neuen Datensatz definieren, der die Protokolle von einem vorhandenen Typ "erbt"?Wie Protokollmethoden zu vorhandenen Typ weitergeleitet werden?

Um diese Frage klar zu machen, werde ich mit der Erweiterung Ubergraph veranschaulichen, aber Ubergraph ist nur ein Beispiel; Ich suche nach der allgemeinen Lösung, nicht nur nach einer Lösung, die für Ubergraph funktioniert. Angenommen, ich möchte ein globales Attribut, graph-name, zu Ubergraph hinzufügen. Im Idealfall könnte ich so etwas tun:

(defrecord named-ubergraph [g graph-name]) 

(extend-type named-ubergraph 
    (all-the-protocols-supported-by ubergraph.core.Ubergraph) 
    (call-the-same-functions-replacing-first-argument-with '(this g)) 

Natürlich habe ich an der Ubergraph Quellcode aussehen könnte und manuell alle Weiterleitungsfunktionen schreiben, aber as you can see here, Ubergraph erfüllt viele Protokolle und viele Protokoll Methoden.

So viel Code zu schreiben klingt nicht sehr Clojurely, und es scheint wie viel Arbeit, wenn ich nur ein eensy-weensy Bit Daten zu einem Ubergraph hinzufügen möchte. Was ist ein besserer Weg?

Bitte zögern Sie nicht, die Frage neu zu konzipieren, wenn Sie denken, dass ich das falsch sehe.

Antwort

1

extend-type erweitert bestehende Typen auf bestimmte Protokolle. Wenn ich Sie richtig verstehe, möchten Sie bestehenden Datensatz erweitern, um eine Art von Vererbung zu erreichen. AFAIK, es gibt keinen einfachen Weg, dies zu tun. ist jedoch, wenn alles, was Sie wollen, ein weiteres Feld hinzuzufügen, können Sie einfach assoc zusätzliches Feld zu einem vorhandenen Datensatz Beispiel:

(defprotocol Cost 
    (cost [this price-list])) 

(defrecord Car [name speed] 
    Cost 
    (cost [this price-list] (price-list (:name this)))) 

(def my-car (->Car "bmw" 200)) 
(def price-list {"bmw" 100000}) 

(cost my-car price-list) 
;;=> 100000 

(-> my-car 
    (assoc :color "blue") 
    (cost price-list)) 
;;=> 100000 

UPDATE: ich auch diese fantastische Diskussion über Clojure Mailing-Liste gefunden haben: defrecord mit "Vererbung": https://groups.google.com/forum/#!topic/clojure/mr-o9sRyiZ0

+0

Nur 'assoziieren 'mit der Aufzeichnung ist ein guter Einblick! Ich wusste, dass Clojure das erlaubte, aber ich hatte im Zusammenhang mit diesem Problem nicht daran gedacht. Dies löst sofort viele meiner aktuellen Probleme - mit der idealen Menge an Code: keine! Ich habe jedoch gerade versucht, einen Ubergraphen zu assoziieren, und das funktioniert nicht. Also, ich lasse die Frage für jetzt offen. (Das Hinzufügen von beliebigen Daten zu einem Ubergraph ist eigentlich der wichtigste praktische Grund, warum ich das gerade brauche.) –

+0

Hmm, Ubergraph hat sogar [case statements] (https://github.com/Engelberg/ubergraph/blob/320e284a6de6adb241df5dfeb9fd6383caea659c/src/ Ubergraph/core.clj # L214), die 'assoziieren' mit beliebigen Schlüsseln verhindern. –

Verwandte Themen