Next: , Previous: , Up: Common Lisp Package System   [Contents][Index]


3.1.2 Syntax of Names

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.

unqualified names

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.

package-qualified names

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.

external symbol

A name containing only a single colon must refer to an external symbol—one that the package exports for public use.

symbol

A double-colon name can refer to any symbol from the named package.

keyword symbol

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.

uninterned symbol

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
shadowing symbol

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.

imported symbol

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.

uninterned symbol

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]