Использование макросов Clojure для DSL - PullRequest
11 голосов
/ 28 марта 2011

Я работаю над проектом Clojure и часто пишу макросы Clojure для DSL, но я смотрел видео Clojure о том, как компания использует Clojure в своей реальной работе, и докладчик сказал, что при практическом использовании они не используют макросы для своих DSL, они используют только макросы для добавления небольшого синтаксического suger. Значит ли это, что я должен написать свой DSL с использованием стандартных функций, а затем добавить несколько макросов в конце?

Обновление : Прочитав много разных (и занимательных) ответов на этот вопрос, я понял, что ответ не так однозначен, как мне показалось, по многим причинам:

  1. В приложении существует множество различных типов API (внутренних, внешних)

  2. Существует много типов пользователей API (бизнес-пользователи, которые просто хотят быстро что-то сделать, эксперт Clojure)

  3. Есть ли здесь макрос, чтобы скрыть код котельной плиты?

Я уйду и подумаю над вопросом более глубоко, но спасибо за ваши ответы, так как они дали мне много думать. Также я заметил, что Пол Грэм считает противоположность видео Кристофа и считает, что макросы должны составлять большую часть кодовой базы (25%):

http://www.paulgraham.com/avg.html

Ответы [ 4 ]

12 голосов
/ 28 марта 2011

В некоторой степени я считаю, что это зависит от использования / цели вашего DSL.

Если вы пишете библиотечный DSL для использования в коде Clojure и хотите, чтобы ониспользовать функционально, тогда я предпочел бы функции макросам.Функции «хороши» для пользователей Clojure, потому что они могут динамически объединяться в функции более высокого порядка и т. Д. Например, вы пишете функциональную веб-среду, такую ​​как Ring .

Если вы пишете императивный DSL, который будет использоваться практически независимо от другого кода Clojure , и вы решили, что вам определенно не нужны функции более высокого порядка, тогда использование будет довольно схожим, и вы сможете выбрать тот, который имеет больше смысла.Например, вы, возможно, создаете какой-то механизм бизнес-правил.

Если вы пишете специализированный DSL , который должен производить высокопроизводительный код , то вы, вероятно, захотите использовать макросы чаще всего.времени, так как они будут расширены во время компиляции для максимальной эффективности.Например, вы пишете некоторый графический код, который необходимо расширить до точно правильной последовательности вызовов OpenGL ......

7 голосов
/ 28 марта 2011

Да!

Пишите функции всякий раз, когда это возможно. Никогда не пишите макрос, когда функция будет делать. Если вы пишете много макросов, вы получаете что-то, что гораздо сложнее расширить. Например, макросы не могут быть применены или переданы.

Кристоф Гранд: (не = макросы DSL)

http://clojure.blip.tv/file/4522250/

3 голосов
/ 28 марта 2011

Нет!

Не бойтесь широко использовать макросы.Всегда пишите макрос, когда сомневаетесь.Функции уступают в реализации DSL - они берут нагрузку на среду выполнения, тогда как макросы позволяют выполнять много тяжеловесных вычислений во время компиляции.Просто представьте себе разницу в реализации, скажем, встроенного Пролога как функции интерпретатора и макроса, который компилирует Пролог в какую-то форму WAM.

И не слушайте тех, кто говорит, что «макросы не могут бытьприменяется или передается ", этот аргумент полностью соломенный.Эти люди защищают интерпретаторы над компиляторами, что просто смешно.

Несколько советов о том, как реализовать DSL с использованием макросов:

  • Делайте это поэтапно.Определите длинную цепочку языков от вашего DSL до базового Clojure.Сделайте каждое преобразование максимально простым - таким образом вы сможете легко поддерживать и отлаживать свой DSL-компилятор.
  • Подготовьте набор инструментов для компонентов DSL, которые вы будете использовать повторно при реализации ваших DSL.Он должен включать целевые языки с различной семантикой (например, нетипизированный нетерпеливый функционал - это сам Clojure, нетипизированный ленивый функционал, логика первого порядка, типизированный императив, тип нетерпеливого функционала Хиндли-Миллера, поток данных и т. Д.).С помощью макросов легко объединить свойства всей целевой семантики.
  • Поддерживать набор инструментов для компиляции.Он должен включать генераторы синтаксического анализатора (полезно, даже если ваши DSL полностью в S-выражениях), механизмы переписывания терминов, механизмы сопоставления с образцом, реализации некоторых распространенных алгоритмов на графах (например, раскраска графов) и т. Д.
2 голосов
/ 28 марта 2011

Вот пример DSL в Haskell, который использует функции, а не макросы:

http://contracts.scheming.org/

Вот видео Саймона Пейтона Джонса, рассказывающего об этой реализации:

http://ulf.wiger.net/weblog/2008/02/29/simon-peyton-jones-composing-contracts-an-adventure-in-financial-engineering/

Используйте характеристики Clojure и FP, прежде чем идти по пути реализации вашего собственного языка. Я думаю, что советы SK-logic дают вам хорошее представление о том, что необходимо для реализации полноценного языка. Бывают времена, когда это стоит усилий, но они редки.

...