Unable to compile file when a defconstant uses a function from the same file

Viewed 136

This is example.lisp:

(defun f (x)
  (* x 2))

(defconstant +n+ (f 1))

When I compile try to compile the file using (compile-file "example.lisp"), I get an error when compiling the constant: The function COMMON-LISP-USER::F is undefined. How can this be? I have already defined the function f before using it to define the constant. How do I define a constant whose value is the return value of a function?

I am using SBCL 2.0.1.

1 Answers

From DEFCONSTANT:

[...] users must ensure that the initial-value can be evaluated at compile time (regardless of whether or not references to name appear in the file) and that it always evaluates to the same value.

But COMPILE-FILE and 3.2.3 File Compilation only require the DEFUN form to establish that F exists, not that is may be evaluated during compilation.

You need to LOAD the resulting file for the definition to be available in your environment (e.g. Slime compiles a file and loads the result). Likewise, when you evaluate forms one at a time in the REPL, the definition becomes available right away, as-if a small compile-load cycle was done.

You have two main options:

  • wrap the defun in an eval-when form

      (eval-when (:compile-toplevel :load-toplevel :execute)
        (defun f (x) (* x 2)))
    
  • put the two forms in distinct files, and have the second one depends in the system (in the defsystem sense) on the first one:

      (defsystem "foo"
        :components ((:file "define-f")
                     (:file "define-constant"))
        :serial t)
    
Related