Reputation: 905
While working through Peter Seibel's book Practical Common Lisp, I've had some difficulty understanding how to handle the Common Lisp package system in conjunction with Emacs's SLIME and quicklisp. The project he supplies has the following structure:
spam.lisp
in the package com.gigamonkeys.spam
, which relies on two other packages, cl-ppcre
and com.gigamonkeys.pathnames
. pathnames.lisp
in the package com.gigamonkeys.pathnames
spam.asd
, which describes the dependencies of com.gigamonkeys.spam
packagepathnames.asd
, which describes the dependencies of the com.gigamonkeys.pathnames
packageThe only way that I've currently found to build the final target, spam.lisp, is to:
pathnames.asd
file using SLIME (C-x C-k
)com.gigamonkeys.pathname
package by typing (asdf:operate 'asdf:load-op 'spam)
at the REPLcl-ppcre
package by typing (ql:quickload "cl-ppcre")
at the REPLspam.asd
file using SLIMEcom.gigamonkeys.spam
package by typing (asdf:operate 'asdf:load-op 'spam)
at the REPLThis seems like an insane amount of work required to use the functions defined in a single file (spam.lisp
) - I've got to be doing something wrong. Is there some way to load spam.lisp
and, recursively, its dependencies, with fewer commands?
Upvotes: 5
Views: 1329
Reputation: 5030
Long story short, packages are bags of symbols and systems describe relationships between files and other systems.
So, using your structure here is a simple system definition:
(asdf:defsystem #:spam-filter
:serial t
:description "Simple Spam Filter"
:author "PCL"
:depends-on (#:cl-ppcre
#:com.gigamonkeys.pathnames)
:components ((:file "package")
(:file "spam")))
Now, I'll suppose the system com.gigamonkeys.pathnames
is in
~/src/lisp/com/gigamonkeys/pathnames/
and the spam filter in
~/src/lisp/spam-filter/
.
slime
RET(push (truename ".") asdf:*central-registry*)
(push (truename ".") asdf:*central-registry*)
(ql:quickload :spam-filter)
Because Quicklisp relies on ASDF to load systems, you've to add the systems directories in ASDF search-path.
You could also put your systems in Quicklisp's search path by adding
them in ~/quicklisp/local-projects/
. You can either store your code
there or use symbolic links.
PS: You can find
here
a slime-shortcut that allows me to write ,addRET
instead of (push (truename ".") asdf:*central-registry*)
.
And just below another slime-shortcut to quickload a system.
(,qlsome-system-name
RET)
Upvotes: 10
Reputation: 139411
A little bit terminology:
a Package is a Common Lisp standard feature. A package is a namespace for symbols. Nothing more. It is not a file, not a module, not a library and not tied to any such thing. It's not even a namespace for functions, variables or classes. Just for symbols. There is a convention to put the definitions that setup a package into a file of its own. But that is just a convention.
a System is used to define, load and compile all files which make up a software library or application. The idea of a System is old (over thirty years). ASDF (Another System Definition Facility) is a popular and free implementation of that idea. Kent Pitman wrote in 1984 about The Description of Large Systems.
A part of such a system facility is a registry, from where all systems can be found. A system definition describes the files it consists of and all the systems it depends on. Typically such a registry is a directory in the file system and/or a registry (a variable, ...) in a running Lisp.
On loading a particular system, the system tool looks into the registry and finds it, loads the definition, loads recursively all needed systems, and then loads all the files.
See the ASDF manual: Configuring ASDF to find your systems
Upvotes: 3