Чому 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.