[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
23.1 Introduction to Symbols | ||
23.2 Obarrays | ||
23.3 Symbol Values |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A symbol is basically just an object with four fields: a name (a string), a value (some Lisp object), a function (some Lisp object), and a property list (usually a list of alternating keyword/value pairs). What makes symbols special is that there is usually only one symbol with a given name, and the symbol is referred to by name. This makes a symbol a convenient way of calling up data by name, i.e. of implementing variables. (The variable’s value is stored in the value slot.) Similarly, functions are referenced by name, and the definition of the function is stored in a symbol’s function slot. This means that there can be a distinct function and variable with the same name. The property list is used as a more general mechanism of associating additional values with particular names, and once again the namespace is independent of the function and variable namespaces.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The identity of symbols with their names is accomplished through a structure called an obarray, which is just a poorly-implemented hash table mapping from strings to symbols whose name is that string. (I say “poorly implemented” because an obarray appears in Lisp as a vector with some hidden fields rather than as its own opaque type. This is an Emacs Lisp artifact that should be fixed.)
Obarrays are implemented as a vector of some fixed size (which should
be a prime for best results), where each “bucket” of the vector
contains one or more symbols, threaded through a hidden next
field in the symbol. Lookup of a symbol in an obarray, and adding a
symbol to an obarray, is accomplished through standard hash-table
techniques.
The standard Lisp function for working with symbols and obarrays is
intern
. This looks up a symbol in an obarray given its name; if
it’s not found, a new symbol is automatically created with the specified
name, added to the obarray, and returned. This is what happens when the
Lisp reader encounters a symbol (or more precisely, encounters the name
of a symbol) in some text that it is reading. There is a standard
obarray called obarray
that is used for this purpose, although
the Lisp programmer is free to create his own obarrays and intern
symbols in them.
Note that, once a symbol is in an obarray, it stays there until
something is done about it, and the standard obarray obarray
always stays around, so once you use any particular variable name, a
corresponding symbol will stay around in obarray
until you exit
XEmacs.
Note that obarray
itself is a variable, and as such there is a
symbol in obarray
whose name is "obarray"
and which
contains obarray
as its value.
Note also that this call to intern
occurs only when in the Lisp
reader, not when the code is executed (at which point the symbol is
already around, stored as such in the definition of the function).
You can create your own obarray using make-vector
(this is
horrible but is an artifact) and intern symbols into that obarray.
Doing that will result in two or more symbols with the same name.
However, at most one of these symbols is in the standard obarray
:
You cannot have two symbols of the same name in any particular obarray.
Note that you cannot add a symbol to an obarray in any fashion other
than using intern
: i.e. you can’t take an existing symbol and put
it in an existing obarray. Nor can you change the name of an existing
symbol. (Since obarrays are vectors, you can violate the consistency of
things by storing directly into the vector, but let’s ignore that
possibility.)
Usually symbols are created by intern
, but if you really want,
you can explicitly create a symbol using make-symbol
, giving it
some name. The resulting symbol is not in any obarray (i.e. it is
uninterned), and you can’t add it to any obarray. Therefore its
primary purpose is as a symbol to use in macros to avoid namespace
pollution. It can also be used as a carrier of information, but cons
cells could probably be used just as well.
You can also use intern-soft
to look up a symbol but not create
a new one, and unintern
to remove a symbol from an obarray. This
returns the removed symbol. (Remember: You can’t put the symbol back
into any obarray.) Finally, mapatoms
maps over all of the symbols
in an obarray.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The value field of a symbol normally contains a Lisp object. However,
a symbol can be unbound, meaning that it logically has no value.
This is internally indicated by storing a special Lisp object, called
the unbound marker and stored in the global variable
Qunbound
. The unbound marker is of a special Lisp object type
called symbol-value-magic. It is impossible for the Lisp
programmer to directly create or access any object of this type.
You must not let any “symbol-value-magic” object escape to
the Lisp level. Printing any of these objects will cause the message
‘INTERNAL EMACS BUG’ to appear as part of the print representation.
(You may see this normally when you call debug_print()
from the
debugger on a Lisp object.) If you let one of these objects escape to
the Lisp level, you will violate a number of assumptions contained in
the C code and make the unbound marker not function right.
When a symbol is created, its value field (and function field) are set
to Qunbound
. The Lisp programmer can restore these conditions
later using makunbound
or fmakunbound
, and can query to
see whether the value of function fields are bound (i.e. have a
value other than Qunbound
) using boundp
and
fboundp
. The fields are set to a normal Lisp object using
set
(or setq
) and fset
.
Other symbol-value-magic objects are used as special markers to
indicate variables that have non-normal properties. This includes any
variables that are tied into C variables (setting the variable magically
sets some global variable in the C code, and likewise for retrieving the
variable’s value), variables that magically tie into slots in the
current buffer, variables that are buffer-local, etc. The
symbol-value-magic object is stored in the value cell in place of
a normal object, and the code to retrieve a symbol’s value
(i.e. symbol-value
) knows how to do special things with them.
This means that you should not just fetch the value cell directly if you
want a symbol’s value.
The exact workings of this are rather complex and involved and are well-documented in comments in ‘buffer.c’, ‘symbols.c’, and ‘lisp.h’.
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated by Aidan Kehoe on December 27, 2016 using texi2html 1.82.