Чому Clojure має 5 способів визначити клас замість одного?


84

Clojure має gen-class, reify, proxy, а також deftype і defrecord для визначення нових типів даних, подібних до класу. Для мови, яка цінує синтаксичну простоту і не хоче зайвої складності, це здається аберрацією. Хтось може пояснити, чому це так? Чи могло бути достатньо декласу в стилі Lisp?

Відповіді:


90

Це поєднання трьох різних факторів:

  1. Конкретна система типів jvm
  2. Необхідність дещо іншої семантики для різних випадків використання при визначенні типів
  3. Справа в тому, що деякі з них були розроблені раніше, а деякі пізніше, коли мова розвивалася.

Тож спочатку давайте розглянемо, що вони роблять. deftype та gen-class подібні тим, що обидва вони визначають іменований клас для попередньої компіляції. Gen-клас був на першому місці, а потім дефтайп в clojure 1.2. Дефтайп є кращим і має кращі експлуатаційні характеристики, але є більш обмежувальним. Клас deftype може відповідати інтерфейсу, але не може успадковувати від іншого класу.

Reify і proxy використовуються для динамічного створення екземпляра анонімного класу під час виконання. Першим став проксі, reify - разом із дефтайпом та дефкордом у clojure 1.2. Переважним є Reify, як і deftype, де семантика не надто обмежує.

Це залишає питання про те, чому і дефтайп, і дефкординг, оскільки вони з'явилися одночасно, і виконують подібну роль. Для більшості цілей ми хочемо скористатися дефкордом: у ньому є всі різноманітні добрі клоджюри, які ми знаємо, і які ми любимо, відокремленість тощо. Deftype призначений для використання в якості будівельного блоку низького рівня для реалізації інших структур даних. Він не включає звичайні інтерфейси clojure, але у нього є опція змінних полів (хоча це не за замовчуванням).

Для подальшого читання перегляньте:

Сторінка типів даних clojure.org

Потік групи Google, де було введено deftype та reify


1
Потік групи Google був дуже цінним. Я розумію, що проксі-сервер Java-interop ген-клас витіснені здебільшого reify та deftype. Я радий, що зараз у нас менше «рекомендованих» способів визначення типів.
— Саліл

2
@Trylks: Можливість розглядати об’єкт як послідовність пар ключ-значення. Практично все, що є рідним для клоджуру, можна розглядати як послідовність, яка є дуже потужною.
— Роб Лахлан

proxyіноді є кращим, оскільки він дозволяє модифікувати методи під час виконання. (наприклад, "Радість Клоджура" , 2-е видання) це може бути корисно для зміни зворотних викликів у веб-обробнику.)
— Марс,

52

Коротка відповідь полягає в тому, що всі вони мають різні та корисні цілі. Складність зумовлена ​​необхідністю ефективного взаємодії з різними особливостями базового JVM.

Якщо вам не потрібна взаємодія Java, то в 99% випадків вам найкраще дотримуватися дефкорду або простої карти Clojure.

  • Якщо ви хочете використовувати протоколи, використовуйте дефрекцію
  • В іншому випадку звичайна карта Clojure, мабуть, найпростіша і найбільш зрозуміла

Якщо ваші потреби більш складні, то наступна блок-схема є чудовим інструментом для пояснення, чому ви вибрали б один із цих варіантів перед іншими:

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

Блок-схема для вибору правильної форми визначення типу Clojure


1
велике спасибі за посилання на блок-схему. Добре допомагає те, що цей блог є співавтором O'reilly's - Programming Clojure. Я думаю, що це прийняття рішень є досить складним. Чи різниця між інтерфейсом та конкретним класом чи необхідністю визначати статичні методи чи ні, або іменований тип чи анонімний тип настільки великі, що їм потрібна інша мовна конструкція?
— Саліл

4
відмінності не є величезними, але вони філософсько відрізняються з точки зору того, чого ви намагаєтесь досягти. Я думаю, що численні підходи в Clojure відображають ці основні відмінності, що є вагомою причиною, чому їм слід давати різні імена.
— mikera

Блок-схема є чудовою, але не охоплює всіх можливостей або причин використання тих чи інших варіантів або їх комбінацій. Жодна проста діаграма не могла.
— Марс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.