Esta é uma mistura de três fatores diferentes:
- O sistema de tipo específico do jvm
- A necessidade de semânticas ligeiramente diferentes para diferentes casos de uso ao definir tipos
- O fato de que alguns deles foram desenvolvidos mais cedo, e alguns mais tarde, conforme a linguagem evoluiu.
Então, primeiro, vamos considerar o que eles fazem. deftype e gen-class são semelhantes no sentido de que ambos definem uma classe nomeada para compilação antecipada. A classe Gen veio primeiro, seguida por deftype no clojure 1.2. Deftype é o preferido e tem melhores características de desempenho, mas é mais restritivo. Uma classe deftype pode estar em conformidade com uma interface, mas não pode herdar de outra classe.
Reify e proxy são usados para criar dinamicamente uma instância de uma classe anônima em tempo de execução. Proxy veio primeiro, reify veio junto com deftype e defrecord no clojure 1.2. Reify é preferido, assim como deftype, onde a semântica não é muito restritiva.
Isso deixa a questão de por que tanto deftype quanto defrecord, uma vez que apareceram ao mesmo tempo e têm uma função semelhante. Para a maioria dos propósitos, queremos usar defrecord: ele tem todas as várias qualidades de clojure que conhecemos e amamos, sequibilidade e assim por diante. Deftype deve ser usado como um bloco de construção de baixo nível para a implementação de outras estruturas de dados. Não inclui as interfaces regulares de clojure, mas tem a opção de campos mutáveis (embora este não seja o padrão).
Para ler mais, confira:
A página de tipos de dados clojure.org
O tópico do grupo do Google em que deftype e reify foram introduzidos