10.3 Creating Symbols

Symbols can be used in two rather different ways. An interned symbol is one that is indexed by its print name in a catalogue called a package. A request to locate a symbol with that print name results in the same (eq) symbol. Every time input is read with the function read, and that print name appears, it is read as the same symbol. This property of symbols makes them appropriate to use as names for things and as hooks on which to hang permanent data objects (using the property list, for example).

Interned symbols are normally created automatically; the first time something (such as the function read) asks the package system for a symbol with a given print name, that symbol is automatically created. The function used to ask for an interned symbol is intern, or one of the functions related to intern.

Although interned symbols are the most commonly used, they will not be discussed further here. For more information, see chapter 11.

An uninterned symbol is a symbol used simply as a data object, with no special cataloguing (it belongs to no particular package). An uninterned symbol is printed as #: followed by its print name. The following are some functions for creating uninterned symbols.

[Function] make-symbol print-name

(make-symbol print-name) creates a new uninterned symbol, whose print name is the string print-name. The value and function bindings will be unbound and the property list will be empty.

The string actually installed in the symbol’s print-name component may be the given string print-name or may be a copy of it, at the implementation’s discretion. The user should not assume that (symbol-name (make-symbol x)) is eq to x, but also should not alter a string once it has been given as an argument to make-symbol. ______________________________________________

Implementation note: An implementation might choose, for example, to copy the string to some read-only area, in the expectation that it will never be altered.

___________________________________________________________________________________________________________

[Function] copy-symbol sym &optional copy-props

This returns a new uninterned symbol with the same print name as sym.

X3J13 voted in March 1989 that the print name of the new symbol is required to be the same only in the sense of string=; in other words, an implementation is permitted (but not required) to make a copy of the print name. User programs should not assume that the print names of the old and new symbols will be eq, although they may happen to be eq in some implementations.

If copy-props is non-nil, then the initial value and function definition of the new symbol will be the same as those of sym, and the property list of the new symbol will be a copy of sym’s.

X3J13 voted in March 1989 to clarify that only the top-level conses of the property list are copied; it is as if (copy-list (symbol-plist sym)) were used as the property list of the new symbol.

If copy-props is nil (the default), then the new symbol will be unbound and undefined, and its property list will be empty.


[Function] gensym &optional x

gensym invents a print name and creates a new symbol with that print name. It returns the new, uninterned symbol.

The invented print name consists of a prefix (which defaults to G), followed by the decimal representation of a number.

gensym is usually used to create a symbol that should not normally be seen by the user and whose print name is unimportant except to allow easy distinction by eye between two such symbols. The optional argument is rarely supplied. The name comes from “generate symbol,” and the symbols produced by it are often called “gensyms.”

If it is desirable for the generated symbols to be interned, and yet guaranteed to be symbols distinct from all others, then the function gentemp may be more appropriate to use.

X3J13 voted in March 1989 to alter the specification of gensym so that supplying an optional argument (whether a string or a number) does not alter the internal state maintained by gensym. Instead, the internal counter is made explicitly available as a variable named *gensym-counter*.

If a string argument is given to gensym, that string is used as the prefix; otherwise “G” is used. If a number is provided, its decimal representation is used, but the internal counter is unaffected. X3J13 deprecates the use of a number as an argument.


[Variable] *gensym-counter*

*gensym-counter* holds the state of the gensym counter; that is, gensym uses the decimal representation of its value as part of the generated name and then increments its value.

The initial value of this variable is implementation-dependent but will be a non-negative integer.

The user may assign to or bind this variable at any time, but its value must always be a non-negative integer.


[Function] gentemp &optional prefix package

gentemp, like gensym, creates and returns a new symbol. gentemp differs from gensym in that it interns the symbol (see intern) in the package (which defaults to the current package; see *package*). gentemp guarantees the symbol will be a new one not already existing in the package. It does this by using a counter as gensym does, but if the generated symbol is not really new, then the process is repeated until a new one is created. There is no provision for resetting the gentemp counter. Also, the prefix for gentemp is not remembered from one call to the next; if prefix is omitted, the default prefix T is used.


[Function] symbol-package sym

Given a symbol sym, symbol-package returns the contents of the package cell of that symbol. This will be a package object or nil.


[Function] keywordp object

The argument may be any Lisp object. The predicate keywordp is true if the argument is a symbol and that symbol is a keyword (that is, belongs to the keyword package). Keywords are those symbols that are written with a leading colon. Every keyword is a constant, in the sense that it always evaluates to itself. See constantp.