Читайте макросы: для чего вы их используете?
Я пытаюсь понять те части Lisp, которые я не очень использовал до сих пор. В настоящее время мои макросы привлекли мое внимание. Существует не так много информации об их использовании, и это поможет узнать, что с ними сделали люди, чтобы получить примеры того, как они работают, а также посмотреть, какие проблемы могут быть подошел с ними. Следуя этому, существуют ли какие-либо рекомендации по пониманию того, что представляет собой хорошее и плохое использование прочитанных макросов?
Ответы
Ответ 1
S-выражения представляют собой синтаксис Lisp для данных Lisp. S-выражения считываются с помощью функции READ, а прочитанные макросы - это Lisp встроенный способ расширения чтения. Это означает, что наиболее прямое использование макросов чтения заключается в реализации заранее заданного синтаксиса данных и открытии возможностей для изменения или расширения способа чтения s-выражений Lisp.
Lisp поставляется с предопределенным внешним синтаксисом для множества типов данных: символами, числами, строками, массивами, символами, концами, списками, структурами и т.д. Он позволяет печатать и читать объекты данных.
-
Lisp отсутствует синтаксис для нескольких других типов данных - заметные хэш-таблицы и объекты CLOS. Таким образом, первое использование прочитанных макросов в пользовательском коде должно было бы расширить читатель, чтобы иметь возможность читать структуры данных, такие как хэш-таблицы, параллельные векторы, новые типы номеров,... в основном каждый тип данных, который разработчик хочет иметь внешний синтаксис, который можно прочитать.
-
Так как Lisp использует s-выражения также для кода, второе использование макросов чтения - это расширение обозначений для программ Lisp. Типичным примером является использование [и] для написания встроенного кода SQL. Обычный синтаксис Lisp выглядит аналогичным, но использование [и] помогает выражениям SQL выделяться в коде. Другим примером является использование макросов чтения для предоставления идентификаторов для встроенных языков программирования, таких как константы Objective C, сообщения и т.д. Clozure CL использует это, чтобы представлять идентификаторы, зависящие от случая и сохраняющие регистр, и искать их определение во время чтения с использованием индекса внешние идентификаторы.
-
Третье использование заключается в встраивании различных синтаксисов в синтаксис Lisp. Старый пример для этого - это макрос чтения инфикс, который позволяет встроенные инфиксные выражения. Другими примерами являются встроенный синтаксис HTML или XML или встроенные фрагменты других синтаксисов языка программирования.
-
Иногда считываемые макросы используются для реализации других (родственных) языков, которые используют синтаксисы s-expression, которые отличаются от предопределенного синтаксиса Common Lisp. Примером может служить считыватель для s-выражений Scheme, которые немного отличаются от Common Lisp.
Ответ 2
Макросы Reader используются, когда есть синтаксис для литералов, которые вы можете захотеть. Единственная проблема с ними - это плоское пространство имен для возможных синтаксисов (однако есть способы обойти это).
Существует не так много применений макросов читателя. Вот некоторые примеры, которые приходят мне на ум:
Ответ 3
Я действительно стараюсь избегать их для моего обычного кода Lisp; в последнее время я даже обнаружил, что отказываюсь от сторонней библиотеки из-за использования макросов-читателей. Это в основном связано с тем, что в отличие от символов существует только одно "пространство имен" для считывающих макросов. И я часто не согласен с авторами библиотек об их вкусе при выборе подходящего диспетчерского характера.
Однако я использовал настраиваемые нестандартные readtables + читал успешно для простых задач синтаксического анализа. Самым сложным парсером, который я реализовал до сих пор с помощью пользовательского чтения, был механизм HTML-шаблона (еще один, извините) с синтаксисом, подобным JSP/ASP, но используя Common Lisp в качестве фактического языка шаблонов, чтобы вы могли иметь вещи как
<% (for (title . link) in breadcrumb do %><a href="<%= link %>"><%= title %></a><% ) %>
(не было сделано только с помощью считываемых хакеров, хотя код должен был пройти этап предварительной обработки).
Ответ 4
Хотя я использую много макросов, я никогда не нашел необходимости использовать read-macros, кроме случайных экспериментов. Если это поможет, на "Let Over Lambda" вы найдете подробное обсуждение о них: http://letoverlambda.com/index.cl/toc
Ответ 5
У меня есть два небольших проекта в Github, которые показывают, как и почему можно использовать макросы чтения в Common Lisp. Это SHELLSHOCK и BOXEN. Как упоминалось в других ответах, CL-INTERPOL является выдающимся и полезным примером.
Являются ли это хорошим использованием макросов читателя, очевидно, субъективны, но, безусловно, я должен подумать, что они полезны или я бы не написал код!
Ответ 6
Один особенно распространенный и полезный альтернативный синтаксис, который можно вставлять с помощью макросов чтения, - синтаксис regex. Это совсем не сложно реализовать, поскольку он просто читает строку с разными правилами экранирования, но если вы часто используете регулярные выражения, это может действительно окупиться. Библиотека CL-INTERPOL, о которой упоминается dmitry-vk, предоставляет эту функциональность вместе с лотом других функций.
Ответ 7
См. Всеволода Дёмкина
на мой вопрос Написание Common Lisp кода, который выполняется из командной строки, но не внутри интерпретатора,
который является применением макросов читателя.