Esta es una combinación de tres factores diferentes:
- El sistema de tipos particular de la jvm
- La necesidad de una semántica ligeramente diferente para diferentes casos de uso al definir tipos
- El hecho de que algunos de estos se desarrollaron antes y otros más tarde, a medida que el lenguaje ha evolucionado.
Primero, consideremos qué hacen estos. deftype y gen-class son similares en el sentido de que ambos definen una clase con nombre para la compilación anticipada. Gen-class vino primero, seguido de deftype en clojure 1.2. Se prefiere Deftype y tiene mejores características de rendimiento, pero es más restrictivo. Una clase deftype puede ajustarse a una interfaz, pero no puede heredar de otra clase.
Reify y proxy se utilizan para crear dinámicamente una instancia de una clase anónima en tiempo de ejecución. Proxy vino primero, reify vino junto con deftype y defrecord en clojure 1.2. Se prefiere Reify, al igual que deftype, donde la semántica no es demasiado restrictiva.
Eso deja la pregunta de por qué deftype y defrecord, ya que aparecieron al mismo tiempo y tienen un papel similar. Para la mayoría de los propósitos, querremos usar defrecord: tiene todas las bondades de clojure que conocemos y amamos, sequability, etc. Deftype está diseñado para usarse como un bloque de construcción de bajo nivel para la implementación de otras estructuras de datos. No incluye las interfaces regulares de clojure, pero tiene la opción de campos mutables (aunque este no es el predeterminado).
Para obtener más información, consulte:
La página de tipos de datos de clojure.org
El hilo del grupo de Google donde se introdujeron deftype y reify
proxy
a veces se prefiere porque permite la modificación de métodos en tiempo de ejecución. (por ejemplo, The Joy of Clojure , 2ª ed. sugiere que esto podría ser útil para modificar devoluciones de llamada en un controlador web).La respuesta corta es que todos tienen propósitos diferentes y útiles. La complejidad se debe a la necesidad de interoperar de manera efectiva con diferentes características de la JVM subyacente.
Si no necesita ninguna interoperabilidad de Java , el 99% de las veces es mejor que se quede con defrecord o un simple mapa de Clojure.
Si sus necesidades son más complejas, el siguiente diagrama de flujo es una gran herramienta para explicar por qué elegiría una de estas opciones sobre las otras:
http://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form/
fuente