Common Lisp the Language, 2nd Edition

next up previous contents index
Next: Consistency Rules Up: Common Lisp the Language Previous: Creating Symbols

11. Packages

One problem with earlier Lisp systems is the use of a single name space for all symbols. In large Lisp systems, with modules written by many different programmers, accidental name collisions become a serious problem. Common Lisp addresses this problem through the package system, derived from an earlier package system developed for Lisp Machine Lisp [55]. In addition to preventing name-space conflicts, the package system makes the modular structure of large Lisp systems more explicit.

A package is a data structure that establishes a mapping from print names (strings) to symbols. The package thus replaces the ``oblist'' or ``obarray'' machinery of earlier Lisp systems. At any given time one package is current, and this package is used by the Lisp reader in translating strings into symbols. The current package is, by definition, the one that is the value of the global variable *package*. It is possible to refer to symbols in packages other than the current one through the use of package qualifiers in the printed representation of the symbol. For example, foo:bar, when seen by the reader, refers to the symbol whose name is bar in the package whose name is foo. (Actually, this is true only if bar is an external symbol of foo, that is, a symbol that is supposed to be visible outside of foo. A reference to an internal symbol requires the intentionally clumsier syntax foo::bar.)

The string-to-symbol mappings available in a given package are divided into two classes, external and internal. We refer to the symbols accessible via these mappings as being external and internal symbols of the package in question, though really it is the mappings that are different and not the symbols themselves. Within a given package, a name refers to one symbol or to none; if it does refer to a symbol, then it is either external or internal in that package, but not both.

External symbols are part of the package's public interface to other packages. External symbols are supposed to be chosen with some care and are advertised to users of the package. Internal symbols are for internal use only, and these symbols are normally hidden from other packages. Most symbols are created as internal symbols; they become external only if they appear explicitly in an export command for the package.

A symbol may appear in many packages. It will always have the same name wherever it appears, but it may be external in some packages and internal in others. On the other hand, the same name (string) may refer to different symbols in different packages.

Normally, a symbol that appears in one or more packages will be owned by one particular package, called the home package of the symbol; that package is said to own the symbol. Every symbol has a component called the package cell that contains a pointer to its home package. A symbol that is owned by some package is said to be interned. Some symbols are not owned by any package; such a symbol is said to be uninterned, and its package cell contains nil.

Packages may be built up in layers. From the point of view of a package's user, the package is a single collection of mappings from strings into internal and external symbols. However, some of these mappings may be established within the package itself, while other mappings are inherited from other packages via the use-package construct. (The mechanisms responsible for this inheritance are described below.) In what follows, we will refer to a symbol as being accessible in a package if it can be referred to without a package qualifier when that package is current, regardless of whether the mapping occurs within that package or via inheritance. We will refer to a symbol as being present in a package if the mapping is in the package itself and is not inherited from somewhere else. Thus a symbol present in a package is accessible, but an accessible symbol is not necessarily present.

A symbol is said to be interned in a package if it is accessible in that package and also is owned (by either that package or some other package). Normally all the symbols accessible in a package will in fact be owned by some package, but the terminology is useful when discussing the pathological case of an accessible but unowned (uninterned) symbol.

As a verb, to intern a symbol in a package means to cause the symbol to be interned in the package if it was not already; this process is performed by the function intern. If the symbol was previously unowned, then the package it is being interned in becomes its owner (home package); but if the symbol was previously owned by another package, that other package continues to own the symbol.

To unintern a symbol from the package means to cause it to be not present in the package and, additionally, to cause the symbol to be uninterned if the package was the home package (owner) of the symbol. This process is performed by the function unintern.

next up previous contents index
Next: Consistency Rules Up: Common Lisp the Language Previous: Creating Symbols