Question

I'm currently playing with lispbuilder-sdl on SBCL under Windows.

My source code is as follows:

(asdf:operate 'asdf:load-op :lispbuilder-sdl)
(asdf:operate 'asdf:load-op :lispbuilder-sdl-binaries)
(asdf:operate 'asdf:load-op :lispbuilder-sdl-examples)
(sdl-examples:squashed)

When I compile the file I get the error: package "SDL-EXAMPLES" not found.

If I remove the (sdl-examples:squashed) from the file it compiles ok. I can then type (sdl-examples:squashed) at the repl and the demo game starts fine.

Why is the sdl-examples package found from the repl but not when I compile the file?

Was it helpful?

Solution

All of the compilation of that file happens before executing any of the load-ops. So when Lisp compiles the (sdl-examples:squashed) line, it hasn't run the load-op that defines your package.

You can get around this by not mentioning the sdl-examples package that requires the reader to locate its squashed symbol before the load-op is actually executed:

(funcall (symbol-function (intern (symbol-name '#:squashed)
                                  (find-package (symbol-name '#:sdl-examples)))))

The idea is to calculate the package from its symbolic name, lookup the symbol naming your function, and fetch the function it names - but this way requires that the package exist only when the code is run, not when it is first read. Then your four statements can all be compiled, executed in order, and by the time that last statement is executed, your load-ops will have created the package.


So here's a little more info about what's happening here:

  • Writing '#:some-name refers to a symbol that's not part of any package. So that way we can make a reference to a symbolic name without either (1) assuming its package exists or (2) mucking up some other package with the name.
  • Then '(symbol-name #:some-name) extracts the name of the symbol as a string. Why not just write "some-name"? You could, and it will usually work. But this way is a little more robust for the case of running a "modern-mode" case-sensitive Lisp.
  • The find-package maps a string name to Lisp's representation of a package. Remember, by the time you run this line, your package will exist.
  • intern returns the symbol with the given name that lives in the given package.
  • symbol-function returns the function object (a lambda abstraction, or more likely, its compiled representation) associated with the symbol.
  • And then funcall invokes that function. It is kind of clunky, but unfortunately there's not really a better way to mix calls which load code to create a package with names living in that package in the same file.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top