Книга: Practical Common Lisp
That covers the basics of how to use packages to manage namespaces in several common situations. However, another level of how to use packages is worth discussing—the raw mechanics of how to organize code that uses different packages. In this section I'll discuss a few rules of thumb about how to organize code—where to put your
DEFPACKAGE forms relative to the code that uses your packages via
Because packages are used by the reader, a package must be defined before you can
COMPILE-FILE a file that contains an
IN-PACKAGE expression switching to that package. Packages also must be defined before other
DEFPACKAGE forms can refer to them. For instance, if you're going to
:use COM.GIGAMONKEYS.TEXT-DB in
DEFPACKAGE must be evaluated before the
The best first step toward making sure packages exist when they need to is to put all your
DEFPACKAGEs in files separate from the code that needs to be read in those packages. Some folks like to create a
foo-package.lisp file for each individual package, and others create a single
packages.lisp that contains all the
DEFPACKAGE forms for a group of related packages. Either approach is reasonable, though the one-file-per-package approach also requires that you arrange to load the individual files in the right order according to the interpackage dependencies.
Either way, once all the
DEFPACKAGE forms have been separated from the code that will be read in the packages they define, you can arrange to
LOAD the files containing the
DEFPACKAGEs before you compile or load any of the other files. For simple programs you can do this by hand: simply
LOAD the file or files containing the
DEFPACKAGE forms, possibly compiling them with
COMPILE-FILE first. Then
LOAD the files that use those packages, again optionally compiling them first with
COMPILE-FILE. Note, however, that the packages don't exist until you
LOAD the package definitions, either the source or the files produced by
COMPILE-FILE. Thus, if you're compiling everything, you must still
LOAD all the package definitions before you can
COMPILE-FILE any files to be read in the packages.
Doing these steps by hand will get tedious after a while. For simple programs you can automate the steps by writing a file,
load.lisp, that contains the appropriate
COMPILE-FILE calls in the right order. Then you can just
LOAD that file. For more complex programs you'll want to use a system definition facility to manage loading and compiling files in the right order.
The other key rule of thumb is that each file should contain exactly one
IN-PACKAGE form, and it should be the first form in the file other than comments. Files containing
DEFPACKAGE forms should start with
(in-package "COMMON-LISP-USER"), and all other files should contain an
IN-PACKAGE of one of your packages.
If you violate this rule and switch packages in the middle of a file, you'll confuse human readers who don't notice the second
IN-PACKAGE. Also, many Lisp development environments, particularly Emacs-based ones such as SLIME, look for an
IN-PACKAGE to determine the package they should use when communicating with Common Lisp. Multiple
IN-PACKAGE forms per file may confuse these tools as well.
On the other hand, it's fine to have multiple files read in the same package, each with an identical
IN-PACKAGE form. It's just a matter of how you like to organize your code.
The other bit of packaging mechanics has to do with how to name packages. Package names live in a flat namespace—package names are just strings, and different packages must have textually distinct names. Thus, you have to consider the possibility of conflicts between package names. If you're using only packages you developed yourself, then you can probably get away with using short names for your packages. But if you're planning to use third-party libraries or to publish your code for use by other programmers, then you need to follow a naming convention that will minimize the possibility of name collisions between different packages. Many Lispers these days are adopting Java-style names, like the ones used in this chapter, consisting of a reversed Internet domain name followed by a dot and a descriptive string.