Common Lisp the Language, 2nd Edition

next up previous contents index
Next: Name Conflicts Up: Packages Previous: Translating Strings to

11.4. Exporting and Importing Symbols

Symbols from one package may be made accessible in another package in two ways.

First, any individual symbol may be added to a package by use of the function import. The form (import 'editor:buffer) takes the external symbol named buffer in the editor package (this symbol was located when the form was read by the Lisp reader) and adds it to the current package as an internal symbol. The symbol is then present in the current package. The imported symbol is not automatically exported from the current package, but if it is already present and external, then the fact that it is external is not changed. After the call to import it is possible to refer to buffer in the importing package without any qualifier. The status of buffer in the package named editor is unchanged, and editor remains the home package for this symbol. Once imported, a symbol is present in the importing package and can be removed only by calling unintern.

If the symbol is already present in the importing package, import has no effect. If a distinct symbol with the name buffer is accessible in the importing package (directly or by inheritance), then a correctable error is signaled, as described in section 11.5, because import avoids letting one symbol shadow another.

A symbol is said to be shadowed by another symbol in some package if the first symbol would be accessible by inheritance if not for the presence of the second symbol. To import a symbol without the possibility of getting an error because of shadowing, use the function shadowing-import. This inserts the symbol into the specified package as an internal symbol, regardless of whether another symbol of the same name will be shadowed by this action. If a different symbol of the same name is already present in the package, that symbol will first be uninterned from the package (see unintern). The new symbol is added to the package's shadowing-symbols list. shadowing-import should be used with caution. It changes the state of the package system in such a way that the consistency rules do not hold across the change.

The second mechanism is provided by the function use-package. This causes a package to inherit all of the external symbols of some other package. These symbols become accessible as internal symbols of the using package. That is, they can be referred to without a qualifier while this package is current, but they are not passed along to any other package that uses this package. Note that use-package, unlike import, does not cause any new symbols to be present in the current package but only makes them accessible by inheritance. use-package checks carefully for name conflicts between the newly imported symbols and those already accessible in the importing package. This is described in detail in section 11.5.

Typically a user, working by default in the user package, will load a number of packages into Lisp to provide an augmented working environment, and then call use-package on each of these packages to allow easy access to their external symbols. unuse-package undoes the effects of a previous use-package. The external symbols of the used package are no longer inherited. However, any symbols that have been imported into the using package continue to be present in that package.

There is no way to inherit the internal symbols of another package; to refer to an internal symbol, the user must either make that symbol's home package current, use a qualifier, or import that symbol into the current package.

The distinction between external and internal symbols is a primary means of hiding names so that one program does not tread on the namespace of another.

When intern or some other function wants to look up a symbol in a given package, it first looks for the symbol among the external and internal symbols of the package itself; then it looks through the external symbols of the used packages in some unspecified order. The order does not matter; according to the rules for handling name conflicts (see below), if conflicting symbols appear in two or more packages inherited by package X, a symbol of this name must also appear in X itself as a shadowing symbol. Of course, implementations are free to choose other, more efficient ways of implementing this search, as long as the user-visible behavior is equivalent to what is described here.

The function export takes a symbol that is accessible in some specified package (directly or by inheritance) and makes it an external symbol of that package. If the symbol is already accessible as an external symbol in the package, export has no effect. If the symbol is directly present in the package as an internal symbol, it is simply changed to external status. If it is accessible as an internal symbol via use-package, the symbol is first imported into the package, then exported. (The symbol is then present in the specified package whether or not the package continues to use the package through which the symbol was originally inherited.) If the symbol is not accessible at all in the specified package, a correctable error is signaled that, upon continuing, asks the user whether the symbol should be imported.

The function unexport is provided mainly as a way to undo erroneous calls to export. It works only on symbols directly present in the current package, switching them back to internal status. If unexport is given a symbol already accessible as an internal symbol in the current package, it does nothing; if it is given a symbol not accessible in the package at all, it signals an error.

next up previous contents index
Next: Name Conflicts Up: Packages Previous: Translating Strings to