Macros 不在sbcl(公共lisp)中加载文件而编译宏的文件

Macros 不在sbcl(公共lisp)中加载文件而编译宏的文件,macros,compilation,common-lisp,sbcl,Macros,Compilation,Common Lisp,Sbcl,我有一个带有一些lisp代码的文件,我想把它编译成fasl。我正在定义一些函数和宏,它们使用其中的一些函数,以及更多使用这些宏的函数 所以当我试图用 $ sblc --eval "(compile-file \"file.lisp\")" --eval "(quit)" 由于函数未定义,宏无法展开,因此出现编译错误。但一切都是按照正常顺序进行的: ; compiling (DEFUN MY-FUNCTION ...) ; compiling (DEFMACRO MY-MACRO-THAT-US

我有一个带有一些lisp代码的文件,我想把它编译成fasl。我正在定义一些函数和宏,它们使用其中的一些函数,以及更多使用这些宏的函数

所以当我试图用

$ sblc --eval "(compile-file \"file.lisp\")" --eval "(quit)"
由于函数未定义,宏无法展开,因此出现编译错误。但一切都是按照正常顺序进行的:

; compiling (DEFUN MY-FUNCTION ...)
; compiling (DEFMACRO MY-MACRO-THAT-USES-MY-FUNCTION ...)
; compiling (DEFUN OTHER-FUNCTION-THAT-USES-MACRO ...)
; file: /path/to/file/file.lisp
; in: DEFUN OTHER-MY-FUNCTION-THAT-USES-MACRO
;     (MY-MACRO-THAT-USES-MY-FUNCTION 1)
; 
; caught ERROR:
;   during macroexpansion of (MY-MACRO-THAT-USES-MY-FUNCTION 1). Use *BREAK-ON-SIGNALS* to
;   intercept.
;    The function COMMON-LISP-USER::MY-FUNCTION is undefined.
然后我尝试先加载文件,然后再编译它:

sbcl --eval "(load \"file.lisp\")" --eval "(compile-file \"file.lisp\")" --eval "(quit)"
这样做没有任何警告或错误

但这种解决方案看起来很难看,因为:

1) 我需要指定两次文件(即使我编写bash脚本,看起来也不太好)

2) 看起来文件被编译了两次:第一次是在加载时,第二次是在实际编译时

3) 如果我从
repl
执行此操作,文件将加载到其中,有时这可能会很糟糕。如果我只想编译文件,但不想加载它呢

因此,我在这里看到3个变体:

1) 我做错了什么事

2) 我需要将宏和函数重新组合到几个文件中,并使用
load
只加载必要的函数,而不是整个文件。(这无助于解决任何问题,但会降低问题的重要性)

3) 有一个命令可以做我想做的事情,但我就是找不到它

那么我应该如何编译这种类型的文件呢?
提前感谢您的帮助。

这是一个常见的问题。可能已经回答了Stackoverflow问题

  • 在编译过程中,会生成函数代码,但不会加载到编译器中
  • 宏OTOH也可以在编译时环境中使用
两种解决方案:

  • 单独的文件:一个定义宏和所需函数的文件,另一个使用宏的文件。在编译依赖文件之前,请加载宏及其支持代码

  • 使用
    EVAL-WHEN
    :加载顶层
    :编译顶层
    :围绕编译时需要的函数执行
    :compile toplevel
    确保在编译期间执行的顶级代码比任何封闭的顶级代码都多-对于
    defun
    ,这也将在编译时定义函数

见:

注意,在您的示例中不需要两个eval。您还可以编写
--eval”(progn(load…(compile file…)
或甚至
--eval”(let((file…)(load file)(compile file file))