Next: The Three Standard Packages, Previous: The Reader and the Evaluator, Up: Common Lisp Package System [Contents][Index]
A package is like a table that maps strings to symbols. Each package has a name, which can be used to find the package using the function:
find-package.
The two key functions that the reader uses to access the name-to-symbol mappings in a package are:
find-symbol
looks in the package for a symbol with the given string for
a name and returns it, or ‘nil’ if no symbol is found. All the symbols found
in a given package using find-symbol
are said to be accessible in that
package. In other words, the accessible symbols in a package are those that
can be referred to with unqualified names when the package is current.
A symbol can be accessible in two ways. The first is for the package’s name-to-symbol table to contain an entry for the symbol, in which case the symbol is present in the package. The second way a symbol can be accessible in a package is if the package inherits it. A package inherits symbols from other packages by using the other packages. Only external symbols in the used packages are inherited. A symbol is made external in a package by exporting it. An exported symbol can be referred to by use of a single colon qualified name.
intern
will return an existing symbol; otherwise it creates a new symbol with the string as its name and adds it to the package.
When the reader interns a new symbol in the package, it is added to the package’s name-to-symbol table. The package in which a symbol is first interned is called the symbol’s home package.
Both of these functions take a string and, optionally, a package. The ‘package’ argument defaults to the value of the global variable ‘*PACKAGE*’, also called the current package.
Most names you use are unqualified, that is, contain
no colons. When the reader reads such a name, it translates it to a symbol by
converting any unescaped letters to uppercase and passing the resulting
string to intern
. Thus, each time the reader reads the same name in the
same package, it will get the same symbol object. The evaluator uses the
object identity of symbols to determine which function, variable, or the
program element a given symbol refers to.
A name containing either a single colon or a double colon is a package-qualified name. When the reader reads a package-qualified name, it splits the name on the colons and uses the first part as the name of a package and the second part as the name of a symbol. The reader looks up the appropriate package and uses it to translate the symbol name to a symbol object.
A name containing only a single colon must refer to an external symbol—one that the package exports for public use.
A double-colon name can refer to any symbol from the named package.
written with names starting with a colon. Such symbols are interned in the package named ‘KEYWORD’ and automatically exported. When the reader interns a symbol in the ‘KEYWORD’, it also defines a constant variable with the symbol as both its name and value. This is why you can use keywords in argument lists without quoting them–when they appear in a value position, they evaluate to themselves. The names of keyword symbols, like all symbols, are converted to all uppercase by the reader before they are interned. The name does not include the leading colon.
are written with a leading ‘#:’. These names (minus the ‘#:’) are converted to uppercase as normal and then translated into symbols, but the symbols are not interned in any package; each time the reader reads a ‘#:’ name, it creates a new symbol. You will rarely, if ever, write this syntax yourself, but you will sometimes see it when you print an s-expression containing symbols returned by the function ‘GENSYM’.
(gensym) ==> #:G3128
To keep the mappings from names to symbols deterministic, the package system allows only one symbol to be accessible in a given package for each name. That is, a package cannot have a present symbol and an inherited symbol with the same name or inherit two different symbols, from different packages, with the same name. However, you can resolve conflicts by making one of the accessible symbols a shadowing symbol, which makes the other symbols of the same name inaccessible. Each package maintains a list of shadowing symbols.
An existing symbol can be imported into another package by adding it to the package’s name-to-symbol table. Thus, the same symbol can be present in multiple packages.
A present symbol can be uninterned from a package, which causes it to be removed from the name-to-symbol table, and, if it is a shadowing symbol, from the shadowing list. A symbol that isn’t present in any package is called an uninterned symbol, can no longer be read by the reader, will be printed using the ‘#:’ syntax.
Next: The Three Standard Packages, Previous: The Reader and the Evaluator, Up: Common Lisp Package System [Contents][Index]