Почему у Clojure есть 5 способов определить класс вместо одного? - PullRequest
79 голосов
/ 22 августа 2011

Clojure имеет gen-класс, reify, proxy, а также deftype и defrecord для определения новых типов классов. Для языка, который ценит синтаксическую простоту и не терпит ненужной сложности, это выглядит как аберрация. Может кто-нибудь объяснить, почему это так? Может ли обычного дефлекса в стиле Лиспа хватить?

Ответы [ 2 ]

87 голосов
/ 22 августа 2011

Это смесь трех разных факторов:

  1. Особая система типов jvm
  2. Потребность в немного другой семантике для разных случаев использования при определении типов
  3. Тот факт, что некоторые из них были разработаны ранее, а некоторые позже, по мере развития языка.

Итак, давайте сначала рассмотрим, что они делают. deftype и gen-class похожи в том, что они оба определяют именованный класс для досрочной компиляции. На первом месте был Gen-класс, за которым последовал deftype в версии 1.2. Deftype является предпочтительным и имеет лучшие рабочие характеристики, но является более ограничительным. Класс deftype может соответствовать интерфейсу, но не может наследоваться от другого класса.

Reify и proxy используются для динамического создания экземпляра анонимного класса во время выполнения. Прокси появился первым, reify вышел вместе с deftype и defrecord в версии 1.2. Reify предпочтителен, как и deftype, где семантика не слишком ограничительна.

Это оставляет вопрос о том, почему и deftype, и defrecord, поскольку они появились в одно и то же время, и играют сходную роль. Для большинства целей мы захотим использовать defrecord: он обладает всеми различными добродетелями clojure, которые мы знаем и любим, sequability и так далее. Deftype предназначен для использования в качестве низкоуровневого стандартного блока для реализации других структур данных. Он не включает в себя обычные интерфейсы clojure, но у него есть опция изменяемых полей (хотя это не значение по умолчанию).

Для дальнейшего чтения ознакомьтесь:

Страница типов данных clojure.org

Тема группы Google, где были введены deftype и reify

49 голосов
/ 22 августа 2011

Короткий ответ: все они имеют разные и полезные цели.Сложность связана с необходимостью эффективного взаимодействия с различными функциями базовой JVM.

Если вам не требуется какое-либо Java-взаимодействие , то в 99% случаев вам лучше всего придерживатьсяс помощью defrecord или простой карты Clojure.

  • Используйте defrecord, если вы хотите использовать протоколы
  • В противном случае обычная карта Clojure, вероятно, является самой простой и понятной

Если ваши потребности более сложны, тогда следующая блок-схема - отличный инструмент для объяснения, почему вы выбрали бы один из этих вариантов среди других:

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

Flowchart for choosing the right clojure type definition form

...