Spec-Zone.ru › Elisp

Расширение вызова макроса

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

Вычисление вызова макроса начинается так же, как вычисление вызова функции, за исключением одного существенного различия: аргументы макроса — это фактические выражения, появляющиеся в вызове макроса. Они не вычисляются до тех пор, пока не будут переданы определению макроса. В отличие от этого, аргументы функции — это результаты вычисления элементов списка вызова функции.

Получив аргументы, Lisp вызывает определение макроса так же, как вызывается функция. Переменные аргументов макроса привязываются к значениям аргументов из вызова макроса или к списку этих значений в случае аргумента &rest. И тело макроса выполняется и возвращает свое значение так же, как и тело функции.

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

Поскольку расширение вычисляется в обычном режиме, оно может содержать вызовы других макросов. Оно может даже быть вызовом того же макроса, хотя это и необычно.

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

Вы можете увидеть расширение данного вызова макроса, вызвав macroexpand.

Функция: macroexpand форма &необязательный_окружение

Эта функция расширяет форму, если это вызов макроса. Если результат — это другой вызов макроса, он расширяется, пока не получится что-то, что не является вызовом макроса. Это значение, возвращаемое macroexpand. Если форма изначально не является вызовом макроса, она возвращается в том виде, в котором была предоставлена.

Обратите внимание, что macroexpand не рассматривает подвыражения формы (хотя некоторые определения макросов могут это делать). Даже если они сами являются вызовами макросов, macroexpand их не расширяет.

Функция macroexpand не расширяет вызовы встроенных функций. Обычно в этом нет необходимости, так как вызов встроенной функции не сложнее для понимания, чем вызов обычной функции.

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

(defmacro inc (var)
    (list 'setq var (list '1+ var)))
(macroexpand '(inc r))
     ⇒ (setq r (1+ r))
(defmacro inc2 (var1 var2)
    (list 'progn (list 'inc var1) (list 'inc var2)))
(macroexpand '(inc2 r s))
     ⇒ (progn (inc r) (inc s))  ; inc not expanded here.
Функция: macroexpand-all форма &необязательный_окружение

macroexpand-all расширяет макросы так же, как и macroexpand, но будет искать и расширять все макросы в форме, а не только на верхнем уровне. Если макросы не расширены, возвращаемое значение — eq для формы.

Повторяя пример, использованный для macroexpand выше с macroexpand-all, мы видим, что macroexpand-all действительно расширяет вложенные вызовы inc:

(macroexpand-all '(inc2 r s))
     ⇒ (progn (setq r (1+ r)) (setq s (1+ s)))
Функция: macroexpand-1 форма &необязательный_окружение

Эта функция расширяет макросы так же, как и macroexpand, но она выполняет только один шаг расширения: если результат — это другой вызов макроса, macroexpand-1 его не расширит.

Copyright © 1990-1996, 1998-2022 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Expansion.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API