ASDF PSA: defpackage in .asd is not obligatory
Wednesday, November 25th, 2009 17:06There seems to be a recurring misconception about writing .asd files. It is not necessary to start your asd with (defpackage :foo.system ...) (in-package :foo.system) to “avoid polluting the package asdf loads your system in”.
Every time an .asd file is loaded, ASDF creates a fresh package to load it in. The relevant code from ASDF is:
(defun make-temporary-package ()
(flet ((try (counter)
(ignore-errors
(make-package (format nil "ASDF~D" counter)
:use '(:cl :asdf)))))
(do* ((counter 0 (+ counter 1))
(package (try counter) (try counter)))
(package package))))
(defun find-system (...)
...
(let ((package (make-temporary-package)))
(unwind-protect
(let ((*package* package))
...
(load on-disk))
(delete-package package)))
...)
So, whenever you load an asd file, the package is fresh and :uses CL and ASDF.
There are reasons to define a package for your asdf system definition.
- If you are creating any classes, such as custom ASDF component types, then, since classes are not garbage collected (MOP specifies that the list of a class's subclasses can be retrieved, and no implementation I know of uses weak references for the purpose), naming them with symbols in a consistent package (rather than the asdf temporary package) ensures that reloading the system definition does not create useless additional copies of the classes.
- If you are defining functions or other named entities in your system definition (which should of course only be done if they are also necessary to load the system) and want to be able to refer to them, such as for debugging, with nice interned symbol names.
- If you want to be able to
(load "foo.asd")rather than going through asdf:find-system.
The disadvantages I can think of for defining a package for your system definitions are that the package list becomes more cluttered (only noticeably if for some strange reason you're loading many system definitions and not loading the defined systems), you're using more of the global package namespace (probably not a significant concern if you use a naming scheme like foo and foo.system), and your code is marginally more complex.
So there are good reasons for (and maybe some against) defpackage in your asd, but package hygiene is not one of them.
[Edited 2009-11-26 to be less worded against defpackage after consideration and feedback.]
(no subject)
Date: 2009-11-26 07:16 (UTC)(no subject)
Date: 2009-11-26 09:49 (UTC)Documentation agrees with Kevin
Date: 2009-11-26 22:10 (UTC)Seems to me that leaving out the defpackage is an optimization that you might do if you know that you (and any other system user) will never load the .asd file by hand. Seems like a dubious optimization to me.
Oddly, by explaining this to me in order to convince me that the defpackage is unnecessary (in some circumstances), Kevin has had the reverse effect. Putting in the defpackage is trivial (I already have an emacs template that does it automatically), and leaving it out might introduce oddities downstream if I later decide to (a) load the file by hand or (b) add a class or method definition (if I do these things I must go back and patch in a defpackage). Thinking about whether a given system definition file actually needs the defpackage seems to me more trouble than always putting one in.
rpg
Re: Documentation agrees with Kevin
Date: 2009-11-27 07:19 (UTC)and explicitly qualify symbols from the ASDF package, you can have both,
no DEFPACKAGE form, and still be able to manually load the .asd file.