Макросы раскрываются при компиляции файла?

13

У меня есть макрос, который необходимо расширять при каждом использовании во время компиляции. Есть ли способ, которым я могу указать, чтобы это было так, не проходя через кодовую базу и тщательно оборачивая каждый вызов eval-when-compile?

Шон Оллред
источник

Ответы:

13

Все макросы, доступные байтовому компилятору, раскрываются во время компиляции. «Достижимый» по сути означает не быть цитируемым.

Тело defuns, defmacros, lambdas, все байтово скомпилировано, когда исходный файл, который содержит их, байтово скомпилирован. Так что да, любой макрос внутри них будет расширен, если он не находится в кавычках ( '). Очень распространенная ошибка - заключать lambdas в кавычки, и, фактически, именно поэтому вы никогда неlambda должны цитировать s .

Это одно из больших преимуществ макросов, поскольку они хорошо написаны и не влияют на производительность во время выполнения. Другое преимущество - это их сила и универсальность, конечно. Недостатком является то, что вы манипулируете синтаксисом, а не объектами, поэтому есть много места для проблем, некоторые неожиданные, другие неизбежные.

Malabarba
источник
7

Как уже объяснял Малабарба, макросы расширяются во время байтовой компиляции. Если файл не скомпилирован, макросы раскрываются при загрузке файла (стремление к расширению макроса).

Не полагайтесь на это, хотя. Это очень плохой стиль. Как правило, вы не можете ожидать, что код, который использует ваш макрос, на самом деле компилируется, и вы, как правило, должны выполнять как можно меньше кода во время компиляции. В частности, используйте макросы редко и только если другого пути нет. Как правило, используйте макросы только для синтаксиса , а не для семантики (или функциональности).

Макросы - это дырявая абстракция. Их расширение жестко запрограммировано в целевой код во время компиляции и не может быть изменено ретроспективно. Целевой код впоследствии зависит от конкретной реализации макроса во время расширения. В частности, это зависит от всех внутренних API, используемых в теле макроса.

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

Свободное использование макросов для функциональности прокладывает дорогу в ад зависимости .

lunaryorn
источник
Очень хорошие моменты, которые следует учитывать при написании или использовании макросов.
Шон Оллред
«Либеральное использование макросов для функциональности прокладывает дорогу в ад зависимости». Еще неделю назад в package.el была ошибка, которая полностью нарушала установку пакета в совершенно законных ситуациях зависимости от макросов.
Малабарба
@Malabarba Хотите предоставить подробности?
lunaryorn
@lunaryorn Вот, пожалуйста . Противная маленькая проблема.
Малабарба
1
@lunaryorn Я согласен, что макросы опасны (я даже отредактирую свой ответ, чтобы он звучал менее похвально :), но я не думаю, что ошибка была конкретным примером этого. Эта ошибка имела другие (менее отягчающие) проявления, которые вообще не связаны с макросами. Это также вызвало проблемы с функциональными зависимостями.
Малабарба