2011-08-22 14 views
75

Clojure tiene gen-class, reify, proxy y también deftype y defrecord para definir nuevos tipos de datos de clase. Para un lenguaje que valora la simplicidad sintáctica y aborrece la complejidad innecesaria, parece una aberración. ¿Podría alguien explicar por qué es así? ¿Podría bastar el defclass del estilo de Lisp común?¿Por qué Clojure tiene 5 formas de definir una clase en lugar de solo una?

Respuesta

82

Esta es una mezcla de tres factores diferentes:

  1. El sistema tipo particular de la JVM
  2. La necesidad de semántica ligeramente diferente para diferentes casos de uso en la definición de tipos
  3. El hecho de que algunos de estos se desarrollaron antes, y algunos más tarde, a medida que el lenguaje ha evolucionado.

Primero, consideremos qué hacen. deftype y gen-class son similares en el sentido de que ambos definen una clase con nombre para la compilación anticipada. Gen-class fue 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 de se utilizan tanto para crear dinámicamente una instancia de una clase anónima en tiempo de ejecución. Proxy fue el 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 rol similar. Para la mayoría de los propósitos, querremos usar defrecord: tiene todas las bondades de clojure que conocemos y amamos, sequability y demás. Deftype está diseñado para ser utilizado 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 esto no es lo predeterminado).

Para la lectura adicional Salida:

The clojure.org datatypes page

The google group thread where deftype and reify were introduced

+1

El hilo de grupo de Google fue muy valioso. Mi entendimiento es para el proxy java interoperabilidad, gen-class son suplantados por reify y deftype principalmente. Me alegro de que tengamos menos formas "recomendadas" para definir tipos ahora. – Salil

+1

Excelente respuesta y gracias por el enlace de la secuencia. –

+0

Lo sentimos, ¿qué significa "sequability"? Google no está ayudando ... – Trylks

42

La respuesta corta es que todos ellos tienen propósitos diferentes y útiles. La complejidad se debe a la necesidad de interoperar eficazmente con las diferentes características de la JVM subyacente.

Si no necesita ninguna interpo de Java, entonces el 99% de las veces es mejor que se quede con cualquiera de los defrecord o un simple mapa de Clojure.

  • Uso defrecord si desea utilizar protocolos
  • De lo contrario un mapa regular de Clojure es probablemente más simple y comprensible

Si sus necesidades son más complejas, a continuación, el siguiente diagrama de flujo es una gran herramienta para explicar por qué se elige una de estas opciones sobre los demás:

http://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form/

Flowchart for choosing the right clojure type definition form

+1

muchas gracias por el enlace al diagrama de flujo. Ayuda que el blog sea del coautor de O'reilly's - Programming Clojure. Creo que esta toma de decisiones es bastante compleja. ¿Las diferencias entre la interfaz y la clase concreta o la necesidad de definir métodos estáticos o no, o el tipo con nombre o el tipo anónimo son tan vastos que necesitan una construcción de lenguaje diferente? – Salil

+3

las diferencias no son grandes, pero son * filosóficamente diferentes * en términos de lo que estás tratando de lograr. Creo que los enfoques múltiples en Clojure reflejan estas diferencias subyacentes, que es una buena razón por la que se les debe dar diferentes nombres. – mikera

+0

+1. No había visto ese diagrama de flujo antes, eso es increíble. –

Cuestiones relacionadas