Глава 8
Макросы

 8.1 Определение макроса
 8.2 Раскрытие макроса
 8.3 Деструктуризация
 8.4 Compiler Macros
 8.5 Environments

Функциональность макросов Common Lisp’а позволяет пользователю определять произвольные функции, которые преобразуют заданные Lisp’овые формы в другие формы, перед тем, как они будут вычислены или скомпилированы. Это делается на уровне выражений, а не на уровне строк, как в других языках. При написании хорошего кода макросы важны: они предоставляют возможность писать код, которые ясен и элегантен на пользовательском уровне, но после преобразования становится сложным или более эффективным для выполнения.

Когда eval получает список, у которого car элемент является символом, она ищет локальные определения для этого символа (flet, labels и macrolet). Если поиски не увенчались успехом, она ищет глобальное определение. Если это глобальное определение является макросом, тогда исходный список называется макровызовом. С определением будет ассоциирована функция двух аргументов, называемая функцией раскрытия. Эта функция вызывается с макровызовом в качестве первого аргумента и лексическим окружением в качестве второго. Функция должна вернуть новую Lisp’овую форму, называемую раскрытием макровызова. (На самом деле участвует более общий механизм, смотрите macroexpand.) Затем это раскрытие выполняется по месту оригинальной (исходной) формы.

Когда функция компилируется, все макросы, в ней содержащиеся, раскрываются во время компиляции. Это значит, что определение макроса должно быть прочитано компилятором до его первого использования.

В целом, реализация Common Lisp’а имеет большую свободу в выборе того, когда в программе раскрываются макровызовы. Например, допускается для оператора defun раскрытие всех внутренних макровызовов в время выполнения формы defun и записи полностью раскрытого тела функции, как определение данной функции для дальнейшего использования. (Реализация может даже выбрать путь, все время компилировать функции определённые с помощью defun, даже в режиме «интерпретации».)

Для правильного раскрытия макросы должны быть написаны так, чтобы иметь наименьшие зависимости от выполняемого окружения. Лучше всего удостовериться, что все определения макросов доступны перед тем, как компилятор или интерпретатор будет обрабатывает код, содержащий макровызовы к ним.

В Common Lisp, макросы не являются функциями. В частности, макросы не могут использоваться, как функциональные аргументы к таким функциям, как apply, funcall или map. В таких ситуациях список, отображающий «первоначальный макровызов» не существует и не может существовать, потому что в некотором смысле аргументы уже были вычислены.