Next: Cells, Previous: Booleans, Up: Miscellaneous Datatypes
MIT/GNU Scheme provides two types of symbols: interned and
uninterned. Interned symbols are far more common than uninterned
symbols, and there are more ways to create them. Interned symbols have
an external representation that is recognized by the procedure
read
; uninterned symbols do not.1
Interned symbols have an extremely useful property: any two interned
symbols whose names are the same, in the sense of string=?
, are
the same object (i.e. they are eq?
to one another). The term
interned refers to the process of interning by which this is
accomplished. Uninterned symbols do not share this property.
The names of interned symbols are not distinguished by their alphabetic
case. Because of this, MIT/GNU Scheme converts all alphabetic
characters in the name of an interned symbol to a specific case (lower
case) when the symbol is created. When the name of an interned symbol
is referenced (using symbol->string
) or written (using
write
) it appears in this case. It is a bad idea to depend on
the name being lower case. In fact, it is preferable to take this one
step further: don't depend on the name of a symbol being in a uniform
case.
The rules for writing an interned symbol are the same as the rules for
writing an identifier (see Identifiers). Any interned symbol that
has been returned as part of a literal expression, or read using the
read
procedure and subsequently written out using the
write
procedure, will read back in as the identical symbol (in
the sense of eq?
).
Usually it is also true that reading in an interned symbol that was
previously written out produces the same symbol. An exception are
symbols created by the procedures string->symbol
and
intern
; they can create symbols for which this write/read
invariance may not hold because the symbols' names contain special
characters or letters in the non-standard case.2
The external representation for uninterned symbols is special, to
distinguish them from interned symbols and prevent them from being
recognized by the read
procedure:
(string->uninterned-symbol "foo") => #[uninterned-symbol 30 foo]
In this section, the procedures that return symbols as values will either always return interned symbols, or always return uninterned symbols. The procedures that accept symbols as arguments will always accept either interned or uninterned symbols, and do not distinguish the two.
Returns
#t
if object is a symbol, otherwise returns#f
.(symbol? 'foo) => #t (symbol? (car '(a b))) => #t (symbol? "bar") => #f
Returns the name of symbol as a string. If symbol was returned by
string->symbol
, the value of this procedure will be identical (in the sense ofstring=?
) to the string that was passed tostring->symbol
. It is an error to apply mutation procedures such asstring-set!
to strings returned by this procedure.(symbol->string 'flying-fish) => "flying-fish" (symbol->string 'Martin) => "martin" (symbol->string (string->symbol "Malvina")) => "Malvina"Note that two distinct uninterned symbols can have the same name.
Returns the interned symbol whose name is string. Converts string to the standard alphabetic case before generating the symbol. This is the preferred way to create interned symbols, as it guarantees the following independent of which case the implementation uses for symbols' names:
(eq? 'bitBlt (intern "bitBlt")) => #tThe user should take care that string obeys the rules for identifiers (see Identifiers), otherwise the resulting symbol cannot be read as itself.
Returns the interned symbol whose name is string. Converts string to the standard alphabetic case before generating the symbol. If no such interned symbol exists, returns
#f
.This is exactly like
intern
, except that it will not create an interned symbol, but only returns symbols that already exist.
Returns the interned symbol whose name is string. Although you can use this procedure to create symbols with names containing special characters or lowercase letters, it's usually a bad idea to create such symbols because they cannot be read as themselves. See
symbol->string
.(eq? 'mISSISSIppi 'mississippi) => #t (string->symbol "mISSISSIppi") => the symbol with the name "mISSISSIppi" (eq? 'bitBlt (string->symbol "bitBlt")) => #f (eq? 'JollyWog (string->symbol (symbol->string 'JollyWog))) => #t (string=? "K. Harper, M.D." (symbol->string (string->symbol "K. Harper, M.D."))) => #t
Returns a newly allocated uninterned symbol whose name is string. It is unimportant what case or characters are used in string.
Note: this is the fastest way to make a symbol.
Returns a newly allocated uninterned symbol that is guaranteed to be different from any other object. The symbol's name consists of a prefix string followed by the (exact non-negative integer) value of an internal counter. The counter is initially zero, and is incremented after each call to this procedure.
The optional argument object is used to control how the symbol is generated. It may take one of the following values:
- If object is omitted or
#f
, the prefix is"G"
.- If object is an exact non-negative integer, the internal counter is set to that integer prior to generating the result.
- If object is a string, it is used as the prefix.
- If object is a symbol, its name is used as the prefix.
(generate-uninterned-symbol) => #[uninterned-symbol 31 G0] (generate-uninterned-symbol) => #[uninterned-symbol 32 G1] (generate-uninterned-symbol 'this) => #[uninterned-symbol 33 this2] (generate-uninterned-symbol) => #[uninterned-symbol 34 G3] (generate-uninterned-symbol 100) => #[uninterned-symbol 35 G100] (generate-uninterned-symbol) => #[uninterned-symbol 36 G101]
Returns the interned symbol whose name is formed by concatenating the names of the given symbols. This procedure preserves the case of the names of its arguments, so if one or more of the arguments' names has non-standard case, the result will also have non-standard case.
(symbol-append 'foo- 'bar) => foo-bar ;; the arguments may be uninterned: (symbol-append 'foo- (string->uninterned-symbol "baz")) => foo-baz ;; the result has the same case as the arguments: (symbol-append 'foo- (string->symbol "BAZ")) => foo-BAZ
Returns a hash number for symbol, which is computed by calling
string-hash
on symbol's name. The hash number is an exact non-negative integer.
Modulus must be an exact positive integer. Equivalent to
(modulo (symbol-hash symbol) modulus)This procedure is provided for convenience in constructing hash tables. However, it is normally preferable to use
make-strong-eq-hash-table
to build hash tables keyed by symbols, becauseeq?
hash tables are much faster.
This procedure computes a total order on symbols. It is equivalent to
(string<? (symbol->string symbol1) (symbol->string symbol2))
[1] In older dialects of Lisp, uninterned symbols were fairly important. This was true because symbols were complicated data structures: in addition to having value cells (and sometimes, function cells), these structures contained property lists. Because of this, uninterned symbols were often used merely for their property lists — sometimes an uninterned symbol used this way was referred to as a disembodied property list. In MIT/GNU Scheme, symbols do not have property lists, or any other components besides their names. There is a different data structure similar to disembodied property lists: one-dimensional tables (see 1D Tables). For these reasons, uninterned symbols are not very useful in MIT/GNU Scheme. In fact, their primary purpose is to simplify the generation of unique variable names in programs that generate Scheme code.
[2] MIT/GNU Scheme
reserves a specific set of interned symbols for its own use. If you use
these reserved symbols it is possible that you could break specific
pieces of software that depend on them. The reserved symbols all have
names beginning with the characters `#[' and ending with the
character `]'; thus none of these symbols can be read by the
procedure read
and hence are not likely to be used by accident.
For example, (intern "#[unnamed-procedure]")
produces a reserved
symbol.