我有一个带有一些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)有一个命令可以做我想做的事情而我找不到它。
那么我应该如何编译这种类型的文件呢? 提前感谢您的帮助。
答案 0 :(得分:3)
这是一个经常出现的问题。可能已经在Stackoverflow上回答了。
两种解决方案:
单独的文件:一个定义宏和所需的函数,另一个是使用宏的文件。在编译相关文件之前加载宏及其支持代码。
在编译时需要的函数周围使用EVAL-WHEN
:load-toplevel
,:compile-toplevel
和:execute
。 :compile-toplevel
确保在编译期间执行任何封闭的顶级代码 - 对于defun
,这也将在编译时定义函数。
请参阅:http://www.lispworks.com/documentation/HyperSpec/Body/s_eval_w.htm#eval-when
请注意,您的示例中不需要两次逃避。您也可以撰写--eval "(progn (load ...) (compile-file ...))
甚至--eval "(let ((file ...)) (load file) (compile-file file))
。