web-dev-qa-db-fra.com

Pourquoi Clojure a-t-il 5 façons de définir une classe au lieu d'une seule?

Clojure a 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 une complexité inutile, cela ressemble à une aberration. Quelqu'un pourrait-il expliquer pourquoi il en est ainsi? La défclasse commune de style LISP aurait-elle pu suffire?

82
Salil

Il s'agit d'un mélange de trois facteurs différents:

  1. Le système de type particulier du jvm
  2. La nécessité d'une sémantique légèrement différente pour différents cas d'utilisation lors de la définition des types
  3. Le fait que certains d'entre eux ont été développés plus tôt, et d'autres plus tard, au fur et à mesure que le langage a évolué.

Alors d'abord, considérons ce que cela fait. deftype et gen-class sont similaires en ce sens qu'ils définissent tous deux un nom classe pour la compilation à l'avance. Gen-class est venu en premier, suivi du deftype dans clojure 1.2. Le type de deftage est préféré et présente de meilleures caractéristiques de performances, mais il est plus restrictif. Une classe deftype peut se conformer à une interface, mais ne peut pas hériter d'une autre classe.

Reify et proxy sont tous deux utilisés pour créer dynamiquement une instance d'un anonyme classe à l'exécution. Le proxy est venu en premier, reify est venu avec deftype et defrecord dans clojure 1.2. Reify est préféré, tout comme le deftype, où la sémantique n'est pas trop restrictive.

Cela laisse la question de savoir pourquoi à la fois deftype et defrecord, car ils sont apparus en même temps et ont un rôle similaire. Pour la plupart des buts, nous voudrons utiliser la défrocordie: elle a toutes les diverses qualités de clojure que nous connaissons et aimons, la séquençage et ainsi de suite. Deftype est destiné à être utilisé comme un bloc de construction de bas niveau pour la mise en œuvre d'autres infrastructures de données. Il n'inclut pas les interfaces clojure régulières, mais il a l'option de champs mutables (bien que ce ne soit pas la valeur par défaut).

Pour plus de lecture, consultez:

La page des types de données clojure.org

Le fil de discussion du groupe google où deftype et reify ont été introduits

88
Rob Lachlan

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'avez besoin d'aucun Java interop alors 99% du temps, il vaut mieux s'en tenir à l'un ou l'autre des enregistrements ou une simple carte Clojure.

  • Utilisez defrecord si vous souhaitez utiliser des protocoles
  • Sinon, une carte Clojure régulière 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 choisiriez l'une de ces options par rapport aux autres:

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

Flowchart for choosing the right clojure type definition form

51
mikera