Packaging Mechanics
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 **IN-PACKAGE**
.
Because packages are used by the reader, a package must be defined before you can **LOAD**
or **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 COM.GIGAMONKEYS.EMAIL-DB
, then COM.GIGAMONKEYS.TEXT-DB
‘s **DEFPACKAGE**
must be evaluated before the **DEFPACKAGE**
of COM.GIGAMONKEYS.EMAIL-DB
.
The best first step toward making sure packages exist when they need to is to put all your **DEFPACKAGE**
s 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 **DEFPACKAGE**
s 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 **LOAD**
and **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.12
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.