В интерпретаторе Lisp может легко быть ветвь в eval, которая может развернуть макрос и в процессе его расширения вызвать функции для создания расширенного выражения. Я сделал это, прежде чем использовать макросы низкого уровня, и это легко получить.
Но в компиляторе нет никаких функций для вызова расширенного кода: проблему можно увидеть довольно просто в следующем примере:
(defmacro cube (n)
(let ((x (gensym)))
`(let ((,x ,n))
(* ,x ,x ,x))))
Когда макрос расшифровывается интерпретатором, он вызывает gensym и делает то, что вы ожидаете. При расширении компилятором вы создадите код для let, который связывает x с (gensym), но символ gensymmed необходим только для того, чтобы компилятор делал правильные действия. А поскольку gensym фактически не вызывается перед компиляцией макроса, это не очень полезно.
Это становится еще более странным для меня, когда макрос создает список, который будет использоваться в качестве расширения с помощью map или filter.
Итак, как это работает? Конечно, скомпилированный код не скомпилирован в (eval *macro-code*), потому что это было бы ужасно неэффективно. Есть ли хорошо написанный компилятор Lisp, где это ясно?