web-dev-qa-db-fra.com

Où dois-je utiliser defrecord dans clojure?

J'utilise de nombreuses cartes et structures dans mes programmes clojure. Quels sont les avantages (en dehors des performances) de la conversion de ces enregistrements en défrégistrements?

71
Yazz.com

Je considère que les structures sont obsolètes, donc je ne les utilise pas du tout.

Lorsque j'ai un ensemble fixe de clés bien connues utilisées dans de nombreuses instances de carte, je crée généralement un enregistrement. Les gros avantages sont:

  • Performance
  • La classe générée a un type que je peux activer dans plusieurs méthodes ou dans d'autres situations
  • Avec une macro-machinerie supplémentaire autour de l'enregistrement, je peux obtenir la validation de champ, les valeurs par défaut et tout ce que je veux
  • Les enregistrements peuvent implémenter des interfaces ou des protocoles arbitraires (les cartes ne le peuvent pas)
  • Les enregistrements agissent comme des cartes pour la plupart des usages
  • les clés et les valeurs de retour renvoient les résultats dans un ordre stable (par création)

Quelques inconvénients des enregistrements:

  • Étant donné que les enregistrements sont Java (pas les cartes Clojure), il n'y a pas de partage structurel, donc la même structure d'enregistrement utilisera probablement plus de mémoire que la structure de carte équivalente qui a été modifiée. Il y a aussi plus création/destruction d'objets lorsque vous "modifiez" un enregistrement, bien que la machine virtuelle Java soit conçue spécifiquement pour manger ce type de déchets éphémères sans transpirer.
  • Si vous modifiez des enregistrements pendant le développement, vous devrez probablement redémarrer votre REPL plus fréquemment pour récupérer ces modifications. Ce n'est généralement un problème que pendant des périodes de développement étroites.
  • De nombreuses bibliothèques existantes n'ont pas été mises à jour pour prendre en charge les enregistrements (postwalk, Zip, matchure, etc.). Nous avons ajouté ce support au besoin.
88
Alex Miller

Stuart Sierra a récemment écrit un article intéressant sur "Résoudre le problème d'expression avec Clojure 1.2", qui contient également une section sur defrecord:

http://www.ibm.com/developerworks/Java/library/j-clojure-protocols/index.html#datatypes

Je pense que l'article entier est un bon point de départ pour comprendre les protocoles et les enregistrements.

14
Michael Kohl

Un autre avantage majeur est que le disque a un type (sa classe) que vous pouvez expédier.

Un exemple qui utilise cette fonctionnalité mais n'est pas représentatif de toutes les utilisations possibles est le suivant:

(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"
9
bmillare

Utilisez des cartes dans la plupart des cas et des enregistrements uniquement lorsque vous avez besoin de polymorphisme. Avec les cartes seules, vous pouvez toujours utiliser plusieurs méthodes; cependant, vous avez besoin d'enregistrements si vous voulez des protocoles. Compte tenu de cela, attendez d'avoir besoin de protocoles avant de recourir aux enregistrements. Jusque-là, évitez-les en faveur d'un code plus centré sur les données et plus simple.

2
Mario

En plus de ce qui a été noté précédemment, en plus d'être généralement au pair ou supérieur en termes de performances, et en exposant la même interface de programmation qu'une carte, les enregistrements appliquent une structure légère: les noms de clés et le nombre de clés sont appliqués au moment de définition. Cela peut être utile pour éviter des erreurs stupides où la même structure est attendue de nombreuses valeurs (ou simplement artificiellement rigide autrement).

Quelles que soient les motivations d'origine, cette propriété la distingue également des cartes.

0
matanster