changeset 12802:74615e68b2cd

New node, Tips for Defining.
author Richard M. Stallman <rms@gnu.org>
date Tue, 08 Aug 1995 06:15:53 +0000
parents f4e3e478c1b1
children 6dcd5ad16790
files lispref/variables.texi
diffstat 1 files changed, 67 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/lispref/variables.texi	Tue Aug 08 05:16:23 1995 +0000
+++ b/lispref/variables.texi	Tue Aug 08 06:15:53 1995 +0000
@@ -31,6 +31,8 @@
 * Local Variables::       Variable values that exist only temporarily.
 * Void Variables::        Symbols that lack values.
 * Defining Variables::    A definition says a symbol is used as a variable.
+* Tips for Defining::     How to avoid bad results from quitting
+                            within the code to initialize a variable.
 * Accessing Variables::   Examining values of variables whose names
                             are known only at run time.
 * Setting Variables::     Storing new values in variables.
@@ -555,6 +557,71 @@
 level in a file, where normally no local binding is in effect, and make
 sure to load the file before making a local binding for the variable.
 
+@node Tips for Defining
+@section Tips for Defining Variables Robustly
+
+  When defining and initializing a variable that holds a complicated
+value (such as a keymap with bindings in it), it's best to put the
+entire computation of the value into the @code{defvar}, like this:
+
+@example
+(defvar my-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key my-mode-map "\C-c\C-a" 'my-command)
+    @dots{}
+    map)
+  @var{docstring})
+@end example
+
+@noindent
+This method has several benefits.  First, if the user quits while
+loading the file, the variable is either still uninitialized or
+initialized properly, never in-between.  If it is uninitialized,
+reloading the file will initialize it properly.  Second, reloading the
+file once the variable is initialized will not alter it; that is
+important if the user has run hooks to alter part of the contents (such
+as, to rebind keys).  Third, evaluating the @code{defvar} form with
+@kbd{C-M-x} @emph{will} reinitialize the map completely.
+
+  Putting so much code in the @code{defvar} form has one disadvantage:
+it puts the documentation string far away from the line which names the
+variable.  Here's a safe way to avoid that:
+
+@example
+(defvar my-mode-map nil
+  @var{docstring})
+(if my-mode-map
+    nil
+  (let ((map (make-sparse-keymap)))
+    (define-key my-mode-map "\C-c\C-a" 'my-command)
+    @dots{}
+    (setq my-mode-map map)))
+@end example
+
+@noindent
+This has all the same advantages as putting the initialization inside
+the @code{defvar}, except that you must type @kbd{C-M-x} twice, once on
+each form, if you do want to reinitialize the variable.
+
+  But be careful not to write the code like this:
+
+@example
+(defvar my-mode-map nil
+  @var{docstring})
+(if my-mode-map
+    nil
+  (setq my-mode-map (make-sparse-keymap))
+  (define-key my-mode-map "\C-c\C-a" 'my-command)
+  @dots{})
+@end example
+
+@noindent
+This code sets the variable, then alters it, but only if the variable
+had been @code{ni}.  If the user quits just after the @code{setq}, that
+leaves the variable neither correctly initialized nor void nor
+@code{nil}.  Once that happens, reloading the file will not initialize
+the variable; it will remain incomplete.
+
 @node Accessing Variables
 @section Accessing Variable Values