2011-01-03 5 views
18

Ich möchte eine Abstraktion erstellen, die eine Datenbanktabelle darstellt, auf die aber mit allen üblichen Clojure-Seq- und Conj-Programmen und all diesen tollen Dingen zugegriffen werden kann. Gibt es ein Protokoll, das ich hinzufügen muss?In Clojure wie kann ich standardmäßige Clojure-Collection-Schnittstellen auf meinen eigenen Datensätzen und Typen implementieren?

+1

Gibt es einen Grund, warum ein Vektor von Datensätzen als Darstellung nicht ausreicht? (Ich meine das als eine ernsthafte Frage, nicht Snark). Alle APIs von Closure würden mit einer solchen Abstraktion arbeiten. Aus clojures Begründung http://clojure.org/rationale - "Es ist besser, wenn 100 Funktionen auf einer Datenstruktur arbeiten, als 10 Funktionen auf 10 Datenstrukturen haben." - Alan J. Perlis –

+0

Der Grund ist, dass, wenn ich ein Element zum Vektor hinzufügen möchte ich das Element automatisch in einem Datenspeicher beibehalten, und es gibt keine Möglichkeit, dass ich verstecken kann, ohne Con- oder Nachteile oder was auch immer die Add-Funktion ist für Vektoren. – Zubair

+3

Sei super, super vorsichtig mit dieser Art von Dingen. Wenn deine DB nicht unveränderlich ist, lügst du im Grunde über deine Semantik zu Clojure, das kann sehr schnell schiefgehen. Der Großteil von Clojure basiert auf der Idee, dass Sammlungen unveränderlich sind. Daher werden viele Annahmen darüber getroffen, wie bestimmte Funktionen funktionieren. Zum Beispiel sollte die Verwendung von conj für eine Sammlung die Sammlung nicht ändern. Es sollte eine neue Sammlung zurückgeben. Das Brechen dieser Regel könnte bewirken, dass Clojures Funktionen auf sehr seltsame Weise fehlschlagen. –

Antwort

15

Ja. Das Protokoll wird über die Java-Schnittstelle clojure.lang.ISeq definiert. Sie möchten vielleicht clojure.lang.ASeq erweitern, die eine abstrakte Implementierung davon bietet.

Hier ist ein Beispiel: eine seq Abstraktion einer Ressource, die verschließbar ist und automatisch geschlossen wird, wenn die seq endet. (Nicht streng getestet)

(deftype CloseableSeq [delegate-seq close-fn] 
    clojure.lang.ISeq 
    (next [this] 
     (if-let [n (next delegate-seq)] 
     (CloseableSeq. n close-fn) 
     (.close this))) 
    (first [this] (if-let [f (first delegate-seq)] f (.close this))) 
    (more [this] (if-let [n (next this)] n '())) 
    (cons [this obj] (CloseableSeq. (cons obj delegate-seq) close-fn)) 
    (count [this] (count delegate-seq)) 
    (empty [this] (CloseableSeq. '() close-fn)) 
    (equiv [this obj] (= delegate-seq obj)) 
    clojure.lang.Seqable 
    (seq [this] this) 
    java.io.Closeable 
    (close [this] (close-fn))) 
+0

Also verwende ich die extendprotocol Syntax? – Zubair

+0

Die Antwort wurde mit einem Beispiel aktualisiert. –

+0

Brilliant, danke – Zubair

Verwandte Themen