Clojure dispose de gen-class, reify, proxy et également deftype et defrecord pour définir de nouveaux types de données de type classe. Pour un langage qui valorise la simplicité syntaxique et abhorre la complexité inutile, cela semble être une aberration. Quelqu'un pourrait-il expliquer pourquoi il en est ainsi ? Un defclass de style Common Lisp aurait-il pu suffire ?
Réponses
Trop de publicités?C'est un mélange de trois facteurs différents :
- Le système de type particulier de la jvm
- La nécessité d'une sémantique légèrement différente pour les différents cas d'utilisation lors de la définition des types.
- Le fait que certains d'entre eux ont été développés plus tôt, et d'autres plus tard, au fur et à mesure de l'évolution de la langue.
Voyons d'abord ce qu'ils font. deftype y classe générique sont similaires en ce qu'elles définissent toutes deux une classe nommée pour une compilation anticipée. Gen-class est venu en premier, suivi par deftype dans clojure 1.2. Deftype est préféré, et a de meilleures caractéristiques de performance, mais est plus restrictif. Une classe deftype peut se conformer à une interface, mais ne peut pas hériter d'une autre classe.
Réifier y proxy sont toutes deux utilisées pour créer dynamiquement une instance d'une classe anonyme au moment de l'exécution. Proxy est arrivé en premier, reify est arrivé avec deftype et defrecord dans clojure 1.2. Reify est préféré, tout comme deftype, lorsque la sémantique n'est pas trop restrictive.
Cela laisse la question de savoir pourquoi deftype et defrecord, puisqu'ils sont apparus en même temps, et ont un rôle similaire. Dans la plupart des cas, nous voudrons utiliser defrecord : il possède toutes les qualités de Clojure que nous connaissons et aimons, la séquentialité et ainsi de suite. Deftype est destiné à être utilisé comme un bloc de construction de bas niveau pour l'implémentation d'autres structures de données. Il n'inclut pas les interfaces clojure habituelles, mais il a l'option de champs mutables (bien que ce ne soit pas le cas par défaut).
Pour en savoir plus, consultez le site :
Le fil de discussion du groupe Google où deftype et reify ont été présentés.
La réponse courte est qu'ils ont tous des objectifs différents et utiles. La complexité est due à la nécessité d'interopérer efficacement avec les différentes fonctionnalités de la JVM sous-jacente.
Si vous n'ont pas besoin d'interopérabilité avec Java alors, dans 99 % des cas, il est préférable de s'en tenir à defrecord ou à une simple carte Clojure.
- Utilisez defrecord si vous voulez utiliser des protocoles
- Sinon, une carte Clojure ordinaire est probablement la plus simple et la plus compréhensible.
Si vos besoins sont plus complexes, l'organigramme suivant est un excellent outil pour expliquer pourquoi vous choisissez l'une de ces options plutôt que les autres :
http://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form/