Previous | Table of Contents | Next |
The expression (+ 2 (+ 1 1)) does not have any side effects. It only returns the number 4.
If you evaluate the expression, the number 4 is printed; then the Lisp interpreter waits to read an another expression, convert it to its internal form, so it can compute its value, and print that. Hence the term loop in the phrase, read-eval-print loop.
But that is not all. In addition to returning values, the one-time primary task of a Lisp interpreter, it has another job, which is to do other actions, all sorts of other actions: copy files, move the cursor, delete text from the screen, and so on.
For example, when you evaluate (or the computer evaluates for you) the expression:
(re-search-forward ^@node end t)
the value that the expression returns is the location in the buffer that is the end of the occurrence found. At the same time, as a side effect, the expression causes the computer to move point to that location.
You do not always want a side effect. In the program discussed previously, texinfo-menu-first-node, the save-excursion expression is used to undo this side effect caused by re-search-forward: save-excursion causes Emacs to save points initial location and later to return it there. In addition, texinfo-menu-first-node is designed to return the location of the beginning of the line containing the @node, so the last two lines of the definition move point to the beginning of the line and then return that location. This is an example of a function where you mostly do not want side effects, and Emacs makes an effort to avoid them.
On the other hand, many times you do want the side effects and not the returned value. For example, when you use Emacs as an editor, you create, move, change, delete, and save text of one sort or another, whether it be a novel, a mail message, or a program. Most of what you see are the results of side effects. When you type M-f to move forward word by word, you hope to see the cursor move forward; you are not interested in the value returned. When you use sort to alphabetize a list, you do not want the value returned, but you want the alphabetized list.
In those many situations in which you do not want to see the value returned, but only the consequences of the side effect, Emacs prevents clutter and does not show you the value returned.
As a practical matter, when writing Emacs Lisp, it is fairly easy to learn when to and when not to use side effects. re-search-forward moves point to the end of the occurrence found. If you want to see point moved to that location, fine, leave point there; if you do not want point moved, then use save-excursion, as illustrated previously.
In brief, Lisp has two aspects: that understood through the read-eval-print loop, in which computations return a value; and that understood through side effects, in which the computer does something else beside compute.
A variable is a name used in a program to stand for a value. A variable has a standard place in which its current value is always foundthe value cell of a symbol. (Earlier, we described this value cell as one of the drawers in our chest of drawers metaphor.)
Emacs Lisp has three different types of variable: global variables, local variables, and buffer-local variables.7
7There are a few variables of a fourth type, whose values are local to the current terminal; you will not come across these terminal-local variables unless you run Emacs on more than one X Window display. See the section Multiple Displays in The GNU Emacs Lisp Reference Manual.
Global variables are, as the name suggests, in effect throughout your Lisp system, except when overridden locally. Thus, if you set the value of bar to Better Living With Lisp!, bar has that value everywhere in your Lisp system, unless it is superseded locally.
Local variables exist in just a part of a program; hence the name. They are used temporarily. When you define a local variable with the same name as a global variable, the value of the global variable is saved and stashed away; the new value takes its place in the symbols value cell. In the jargon, the new value shadows the old value, so it is not visible. When the local value ceases to be, the global value is placed back into the value cell; that value is restored to the variable.
Buffer-local variables apply only to one buffer. They provide an important means for creating custom modes. For example, both C mode and Lisp mode set the variable paragraph-start to a value different from Text or Texinfo mode. They make the variable buffer local and set it to the value for that mode. Two ways to make a variable buffer local are to use make-local-variable, which only affects the current buffer, leaving all others to continue to share the global value, and make-variable-buffer-local, which makes a variable buffer local in all buffers, but starts out with the global value of the variable.
While global and local variables are found in most programming languages, buffer-local variables are much less common.
Previous | Table of Contents | Next |