在运行时调用macroexpand

时间:2019-06-17 16:12:09

标签: macros lisp common-lisp

是否可以在运行时在已编译的Lisp可执行文件中扩展宏?我希望这是不可能的,因为宏扩展只能在预编译时进行,但是当我在已编译的代码中调用macroexpand时,我会得到输出。

2 个答案:

答案 0 :(得分:4)

在Lisp中,术语“运行时”和“编译时”是指正在处理特定代码段的情况,而不是某些静态语言中的绝对代码。如果我们评估(compile nil '(lambda ())),这是compile函数的运行时,但是lambda表单的编译时:这两个时间是同时发生的。

在所有情况下都可以使用整个语言。当您构建一个独立的可执行文件时,该映像不仅包含对扩展宏的支持,而且还包含对代码进行编译的支持。您的Lisp应用程序可以调用compile-file将Lisp源代码编译为对象形式,并调用load来加载生成的对象代码。

从Lisp应用程序映像中删除垃圾和未使用的功能以使其更小的过程称为"tree shaking"。如果您不希望在应用程序中使用编译器或宏扩展器,请查看是否/如何通过实现的摇晃树技术将其删除。

答案 1 :(得分:3)

宏是通常在编译或评估过程中自动调用的函数,然后将其返回值代替原始表达式进行编译或评估。

但是,由于它只是一个函数,因此也没有阻止它在运行时显式调用的功能,这就是MACROEXPANDMACROEXPAND-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,以使宏定义仅在编译环境中可用。如果这样做,在运行时尝试扩展将失败。

相关问题