2010-06-24 11 views
14

Estoy desarrollando una estructura de datos compleja en Clojure con múltiples subestructuras.Resumen de los detalles de implementación de la estructura de datos en Clojure

Sé que querré ampliar esta estructura con el tiempo, y en ocasiones podría querer cambiar la estructura interna sin romper diferentes usuarios de la estructura de datos (por ejemplo, puede querer cambiar un vector en un hashmap, agregar algún tipo de estructura de indexación por razones de rendimiento, o incorporar un tipo Java)

Mi pensamiento actual es:

  • definir un protocolo para la estructura general con varios métodos de acceso
  • crear una mini-biblioteca de funciones que navegan por la estructura de datos e .gramo. (Consulta de subestructura-abc param1 param2)
  • Implementar la estructura de datos utilizando defrecord o DEFTYPE, con los métodos de protocolo definidos para usar la mini-biblioteca

Creo que esto va a funcionar, aunque me preocupa que está empezando a parecer más como un montón de código de "pegamento". También probablemente también refleja mi mayor familiaridad con los enfoques orientados a objetos.

¿Cuál es la manera recomendada de hacer esto en Clojure?

Respuesta

11

Creo que deftype podría ser el camino a seguir, sin embargo, aprobaría los métodos de acceso. En cambio, mira en clojure.lang.ILookup y clojure.lang.Associative; Estas son interfaces que, si las implementa para su tipo, le permitirán usar get/get-in y assoc/assoc-in, lo que la convierte en una solución mucho más versátil (no solo podrá cambiar la implementación subyacente, sino también usar funciones construidas sobre la biblioteca de colecciones estándar de Clojure para manipular sus estructuras).

Un par de cosas a tener en cuenta:

  1. Usted probablemente debería comenzar con defrecord, utilizando get, assoc & Co. con el estándar defrecord implementaciones de ILookup, Associative, IPersistentMap y java.util.Map. Es posible que puedas recorrer un largo camino con esto.

    Si ya no son suficientes, eche un vistazo a las fuentes de emit-defrecord (una función privada definida en core_deftype.clj en las fuentes de Clojure). Es bastante complejo, pero le dará una idea de lo que puede necesitar implementar.

  2. Ni deftype ni defrecord definen actualmente las funciones de fábrica para usted, pero probablemente debería hacerlo usted mismo. La comprobación de integridad va dentro de esas funciones (y/o las pruebas correspondientes).

  3. Las operaciones conceptualmente más compleja son, por supuesto, un ajuste perfecto para las funciones de protocolo construido sobre la base de get & Co.

Ah, y echar un vistazo a gvec.clj en las fuentes de Clojure para un ejemplo de qué aspecto podría tener algún código de estructura de datos serio escrito usando deftype.La complejidad aquí es de un tipo diferente de lo que describe en la pregunta, pero aún así, es uno de los pocos ejemplos de programación de estructura de datos personalizada en Clojure actualmente disponible para el consumo público (y por supuesto es un código de excelente calidad).

Por supuesto, esto es justo lo que mi intuición me dice en este momento. No estoy seguro de que haya mucho en el camino de los modismos establecidos en esta etapa, lo que con deftype realmente no se ha lanzado y todo. :-)

+0

Gracias Michal! Perspicaz como siempre :-) definitivamente mirará en las opciones de ILookup y Associative – mikera

+0

¡Esta es una respuesta muy útil! Pero casi tres años después sería genial actualizar esto (o crear una nueva respuesta) basado en la función ahora disponible en 1.5. Una cosa que noté es que 'defrecord' ahora emite funciones de fábrica, no estoy seguro de qué otros cambios puedan afectar esta respuesta. –

+0

Creo que esta respuesta también podría usar una actualización, incluso el libro O'Reily Clojure ahora dice que el defrecord de clojure crea funciones de fábrica. – djhaskin987

Cuestiones relacionadas