2011-01-01 22 views

Respuesta

82

considero estructuras parece haber quedado demostrado de manera efectiva por lo que no usarlos en absoluto.

Cuando tengo un conjunto fijo de claves conocidas que se usan en muchas instancias de mapas, normalmente creo un registro. Las grandes ventajas son:

  • Rendimiento
  • clase generada tiene un tipo que pueda encender en métodos múltiples u otras situaciones
  • Con macro maquinaria adicional alrededor defrecord, puedo conseguir la validación de campos, los valores por defecto, y cualquier otra cosa que quiero
  • Los registros pueden implementar interfaces o protocolos arbitrarios (mapas) no pueden
  • Records actuar como mapas para la mayoría de los propósitos
  • llaves y Vals devuelven los resultados en estables (pe r-creación) para

Algunas desventajas de los registros:

  • Debido a que los registros son instancias de clases Java (no mapas de Clojure), no existe un intercambio estructural por lo que la misma estructura de registro es probable que utilice más memoria que la estructura de mapa equivalente que se ha cambiado. También hay más creación/destrucción de objetos a medida que "cambia" un registro, aunque la JVM está diseñada específicamente para comer este tipo de basura de corta duración sin sudar.
  • Si cambia los registros durante el desarrollo, probablemente necesite reiniciar su REPL con mayor frecuencia para recoger esos cambios. Por lo general, esto solo es un problema durante fragmentos pequeños de desarrollo.
  • Muchas bibliotecas existentes no se han actualizado para admitir registros (postwalk, zip, matchure, etc, etc.). Hemos agregado este soporte según sea necesario.
+0

La forma de constructor que describe en su tercer argumento es a lo que se refiere Common Lisp como "Constructor BOA" - * por orden de argumento *, que se usa en tipos de concierto definidos con 'defstruct'. Consulte http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_b.htm#boa_lambda_list. – seh

+0

Hola Alex: creo que verás que los registros sí utilizan el intercambio estructural bajo el capó: implementan una estructura de datos completa y persistente, por lo que mantienen todas las ventajas de los mapas regulares. – mikera

+0

Mikera: un registro genera una clase Java con campos finales. Asociándose a uno debe generar un nuevo objeto Java. Puede reutilizar instancias de campo ya que son inmutables pero no es tan eficiente como un mapa Clojure normal. –

9

Otra ventaja importante es que el registro tiene un tipo (su clase) que puede enviar fuera de.

Un ejemplo que utiliza esta característica, pero no es representativo de todos los usos posibles es la siguiente:

(defprotocol communicate 
    (verbalize [this])) 

(defrecord Cat [hunger-level] 
    communicate 
    (verbalize [this] 
    (apply str (interpose " " (repeat hunger-level "meow"))))) 

(defrecord Dog [mood] 
    communicate 
    (verbalize [this] 
    (case mood 
     :happy "woof" 
     "arf"))) 

(verbalize (->Cat 3)) 
; => "meow meow meow" 

(verbalize (->Dog :happy)) 
; => "woof" 
+1

No realmente, ya que puede enviar en cualquier función, no solo escribir. Puede usar un mapa ordinario y, por ejemplo, agregar otra entrada con una clave llamada "tipo". Luego puede usar una función de despacho que verifique el valor de la entrada "tipo". –

+6

@Goran, que se aplica a multimétodos, mediante el uso de protocolos, solo puede enviar por tipo. A pesar de todo, mi punto era usar defrecords agrega un tipo implícitamente mientras que una defstruct o mapa no agrega automáticamente un tipo. – bmillare

+0

Esta respuesta es muy escueta, un ejemplo podría ser una buena adición. – matanster

2

Usa mapas en la mayoría de los casos y registra solo cuando requieras polimorfismo. Con los mapas solo, puede usar métodos multimétodos; sin embargo, necesita registros si quiere protocolos. Dado esto, espere hasta que necesite protocolos antes de recurrir a los registros. Hasta entonces, evítelos a favor de un código más centrado en los datos y más simple.

0

Además de lo que se ha señalado anteriormente, además de estar a la par o superior en términos de rendimiento y exponer la misma interfaz de programación como un mapa, los registros refuerzan la estructura: los nombres de las teclas y el número de claves se aplican en el momento de la definición. Esto podría ser útil para evitar errores tontos cuando se espera la misma estructura a partir de muchos valores (o de lo contrario es rígida artificialmente).

Sean cuales sean las motivaciones originales, esta propiedad también lo diferencia de los mapas.