Подтвердить что ты не робот

Использование макросов Clojure для DSL

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

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

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

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

Да!

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

Christophe Grand: (не = макросы DSL)

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

Ответ 3

Нет!

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

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

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

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

Ответ 4

Вот пример 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 дают вам хорошее представление о том, что необходимо для внедрения полностью раздутого языка. Бывают моменты, когда это стоит усилий, но это редко.