Pergunta

I have a file with some lisp code and I want to compile it to fasl. I'm defining some functions and macros that use some of that functions and more functions that use these macros.

So when I tried to compile the file with

$ sblc --eval "(compile-file \"file.lisp\")" --eval "(quit)"

I got compilation errors about that the macro couldn't expand because the function is not defined. But everything has been compiling in the normal order:

; 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.

So then I tried to load the file first and then to compile it:

sbcl --eval "(load \"file.lisp\")" --eval "(compile-file \"file.lisp\")" --eval "(quit)"

And this worked without warning or errors.

But this solution looks ugly because of:

1) I need to specify the file twice (even if I write the bash script, this doesn't look so good)

2) It looks like the file is compiled twice: first time when I load it and second time when I actually compile it.

3) If I'll do it from repl, the file will be loaded to it and sometimes this can be bad. What if I just want to compile the file, but not load it?

So I see 3 variant here:

1) I'm doing something completely wrong.

2) I need to regroup macros and functions several files and load only necessary function with load but not the whole file. (this doesn't help with any of the problems but make them less significant)

3) There is a command that does does what I want to do and I just couldn't find it.

So how should I compile such type of files? Thanks for help in advance.

Foi útil?

Solução

That's a frequent question. Probably already answered on Stackoverflow.

  • during compilation, the code of functions is generated, but not loaded into the compiler.
  • macros OTOH are also made available in the compile-time environment

Two solutions:

  • separate files: one which defines macros and the needed functions, another one where the macros are being used. Load the macro and its support code, before compiling dependent files.

  • use EVAL-WHEN with :load-toplevel, :compile-toplevel and :execute around the functions which are needed at compile-time. :compile-toplevel makes sure than any enclosed top-level code gets executed during compilation - for a defun this would define the function at compile-time, too.

See: http://www.lispworks.com/documentation/HyperSpec/Body/s_eval_w.htm#eval-when

Note, that you don't need two evals in your example. You can also write --eval "(progn (load ...) (compile-file ...)) or even --eval "(let ((file ...)) (load file) (compile-file file)).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top