2011-01-03 18 views
18

Deseo crear una abstracción que represente una tabla de base de datos, pero a la que se pueda acceder utilizando todas las funciones y conjunciones habituales de Clojure y todas esas cosas elegantes. ¿Hay algún protocolo que deba agregar?En Clojure, ¿cómo puedo implementar interfaces de recopilación Clojure estándar en mis propios registros y tipos?

+1

¿Hay alguna razón por la que un vector de registros sea insuficiente como representación? (Me refiero a esto como una pregunta seria, no sarcástica). Toda la API de cierre funcionaría con una abstracción de este tipo. De la lógica de clojure http://clojure.org/rationale - "Es mejor tener 100 funciones operando en una estructura de datos que tener 10 funciones operando en 10 estructuras de datos". - Alan J. Perlis –

+0

La razón es que cuando agrego un elemento al vector quiero que el elemento se mantenga automáticamente en un almacén de datos, y no hay manera de que pueda ocultarlo sin volver a implementar conj o contras o lo que sea que la función de agregar sea para Vectores. – Zubair

+3

Sé super, súper cuidadoso con este tipo de cosas. Si DB no es inmutable, básicamente estás mintiendo acerca de tu semántica a Clojure, esto puede salir mal muy rápidamente. La mayor parte de Clojure se basa en la idea de que las colecciones son inmutables. Como tal, se hacen muchas suposiciones sobre el desempeño de ciertas funciones. Por ejemplo, usar conj en una colección no debería cambiar la colección. Debería devolver una nueva colección. Romper esta regla podría causar que las funciones de Clojure fallen de maneras muy extrañas. –

Respuesta

15

Sí. El protocolo está definido por la interfaz Java clojure.lang.ISeq. Es posible que desee extender clojure.lang.ASeq que proporciona una implementación abstracta de la misma.

Aquí hay un ejemplo: una abstracción seq de un recurso que se puede cerrar y se cierra automáticamente cuando termina seq. (No se probó rigurosamente)

(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

Entonces, ¿uso la sintaxis extendprotocol? – Zubair

+0

Se actualizó la respuesta con un ejemplo. –

+0

Brillante, gracias – Zubair

Cuestiones relacionadas