Вызов macroexpand во время выполнения - PullRequest
2 голосов
/ 17 июня 2019

Можно ли развернуть макрос во время выполнения в скомпилированном исполняемом файле lisp? Я ожидал бы, что это будет невозможно, поскольку расширение макроса может произойти только перед компиляцией, но когда я вызываю macroexpand в скомпилированном коде, я получаю вывод.

Ответы [ 2 ]

4 голосов
/ 17 июня 2019

В Лиспе термины «время выполнения» и «время компиляции» - это ситуации, в которых обрабатывается определенный фрагмент кода, а не абсолюты, как в некоторых статических языках.Если мы оценим (compile nil '(lambda ())), то это время выполнения функции compile, но время компиляции формы lambda: оба раза происходят одновременно.

Весь язык доступен во всех ситуациях,Когда вы создаете автономный исполняемый файл, этот образ содержит не только поддержку для расширения макросов, но и для компиляции кода.Ваше приложение Lisp может вызывать compile-file для компиляции исходного кода Lisp в форму объекта и load для загрузки результирующего объектного кода.

Процесс удаления мусора и неиспользуемой функциональности из образа приложения Lisp, чтобы сделать егопоменьше называется "тряска дерева" .Если вы не хотите, чтобы компилятор или макроэкспандер в вашем приложении, выясните, можно ли / как удалить их с помощью поддержки встряхивания дерева вашей реализации.

3 голосов
/ 17 июня 2019

Макрос - это функция, которая обычно вызывается автоматически во время компиляции или вычисления, и ее возвращаемое значение затем компилируется или вычисляется вместо исходного выражения.

Но поскольку это просто функция, ничто не мешает ее явному вызову также во время выполнения, и это то, что MACROEXPAND и MACROEXPAND-1 делают.

Это примерно эквивалентно:

(defun macroexpand-1 (form &optional env)
  (if (and (listp form) (car form)) ;; list expression
      (let ((macfun (macro-function (car form)))
        (if macfun
            (funcall macfun form env)
            form))
      form))

(Обратите внимание, что это определение не обрабатывает макросы символов и не использует *MACROEXPAND-HOOK*, чтобы упростить его.)

Можно использовать EVAL-WHEN при определении макроса, чтобы сделать определение макроса доступным только в среде компиляции. Если вы сделаете это, попытка расширения во время выполнения завершится неудачей.

...