[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

23. Symbols and Variables

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

23.1 Introduction to Symbols

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] [ ? ]

23.2 Obarrays

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] [ ? ]

23.3 Symbol Values

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.