Common Lisp the Language, 2nd Edition
Next: Consistency Rules
Up: Common Lisp the Language
Previous: Creating
Symbols
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: Consistency Rules
Up: Common Lisp the Language
Previous: Creating
Symbols
AI.Repository@cs.cmu.edu