Какая практическая проблема возникает из-за отсутствия гигиенических макросов в Clojure?

11

Я слышал, что макросы Clojure легче писать, но они не так надежны, как гигиенические макросы Racket. Мой вопрос состоит из 2 частей:

  1. Чем gensymотличаются гигиенические макросы?
  2. Что предоставляют макросы Racket, чего нет у Clojure? (будь то безопасность, композитность или что-нибудь)
Alex
источник
2
Гигиенические макросы - это макросы, расширение которых гарантированно не вызовет случайного захвата идентификаторов. Общая проблема случайного захвата была хорошо известна в сообществе Лисп до введения гигиенических макросов. Авторы макросов будут использовать языковые функции, которые будут генерировать уникальные идентификаторы (например, gensym), или использовать запутанные идентификаторы, чтобы избежать проблемы. Гигиенические макросы - это программное решение проблемы захвата, которое интегрировано в сам макроэкспандер. en.wikipedia.org/wiki/Hygienic_macro
Роберт Харви
3
Поскольку гигиеническая макросистема [Racket] обладает глубокими знаниями о том, как работает ваш макрос, ваш макрос чрезвычайно хорошо интегрирован в среду: подсветка синтаксиса работает правильно, автоматическое переименование переменных работает правильно, перекрестные ссылки работают правильно, как и все остальные Slick [Racket] Особенности IDE. Другими словами, гигиена не просто защищает вас от простых ошибок, таких как захват переменных, она позволяет формально анализировать ваш код с помощью инструментов, которые просто не могут существовать для Common LISP. randomhacks.net/2002/09/13/hygienic-macros
Роберт Харви

Ответы:

6

Преимущество гигиенических макросов заключается не в языковых возможностях - вы можете писать макросы с хорошей гигиеной, используя gensymаккуратные цитаты / отрывки в нужное время. Однако гигиенические макросы гарантируют, что ваши макросы имеют хорошую гигиену. В этом отношении это немного похоже на проверку типов.

Там также могут быть преимущества инструментов для гигиенических макросов. Большинство гигиенических макросистем устанавливают строгий контроль над тем, что делает ваш макрос и как он это делает (например, вы не можете выполнить произвольный код, когда макрос, определенный схемами, syntax-caseраскрыт). Это может облегчить написание программ, которые «понимают» ваш макрос и могут обеспечить дополнительную поддержку инструментов.

С другой стороны, в некоторых случаях полезны негигиенические макросы. Например, если вы действительно хотите захватить привязку для определенной переменной (например, анафорических макросов ), то я думаю, что вам не повезло, если у вас есть только гигиенические макросы.

Натан Дэвис
источник
2
gensymпредотвращает случайное взаимодействие макроса с пользователем макроса, но не предотвращает его взаимодействие с макросом. Например, пользователь макроса может переопределить ifили что-то в этом роде. (Вопрос «почему кто-то так поступает» не имеет значения. Это простой пример, демонстрирующий, что это возможно, и сложно рассуждать о негигиенических макросах)
Фил
2
Негигиеничные макросы, безусловно, полезны. Я не уверен насчет Схемы, но в Racket есть много «гигиенических» операций. Макросы языка по умолчанию гигиеничны. Они просто делают вас очень сознательными, когда вы нарушаете гигиену.
Фил