GNU Info

Info Node: (elisp)Tips for Defining

(elisp)Tips for Defining


Next: Accessing Variables Prev: Defining Variables Up: Variables
Enter node , (file) or (file)node

Tips for Defining Variables Robustly
====================================

   When you define a variable whose value is a function, or a list of
functions, use a name that ends in `-function' or `-functions',
respectively.

   There are several other variable name conventions; here is a
complete list:

`...-hook'
     The variable is a normal hook (Note: Hooks).

`...-function'
     The value is a function.

`...-functions'
     The value is a list of functions.

`...-form'
     The value is a form (an expression).

`...-forms'
     The value is a list of forms (expressions).

`...-predicate'
     The value is a predicate--a function of one argument that returns
     non-`nil' for "good" arguments and `nil' for "bad" arguments.

`...-flag'
     The value is significant only as to whether it is `nil' or not.

`...-program'
     The value is a program name.

`...-command'
     The value is a whole shell command.

``'-switches'
     The value specifies options for a command.

   When you define a variable, always consider whether you should mark
it as "risky"; see Note: File Local Variables.

   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 `defvar', like this:

     (defvar my-mode-map
       (let ((map (make-sparse-keymap)))
         (define-key map "\C-c\C-a" 'my-command)
         ...
         map)
       DOCSTRING)

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 still 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 `defvar' form with `C-M-x'
_will_ reinitialize the map completely.

   Putting so much code in the `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:

     (defvar my-mode-map nil
       DOCSTRING)
     (unless my-mode-map
       (let ((map (make-sparse-keymap)))
         (define-key map "\C-c\C-a" 'my-command)
         ...
         (setq my-mode-map map)))

This has all the same advantages as putting the initialization inside
the `defvar', except that you must type `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:

     (defvar my-mode-map nil
       DOCSTRING)
     (unless my-mode-map
       (setq my-mode-map (make-sparse-keymap))
       (define-key my-mode-map "\C-c\C-a" 'my-command)
       ...)

This code sets the variable, then alters it, but it does so in more than
one step.  If the user quits just after the `setq', that leaves the
variable neither correctly initialized nor void nor `nil'.  Once that
happens, reloading the file will not initialize the variable; it will
remain incomplete.


automatically generated by info2www version 1.2.2.9