elisp: Tips for Defining

 
 11.6 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 (SeeHooks).
 
 ‘...-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 success and ‘nil’ for failure.
 
 ‘...-flag’
      The value is significant only as to whether it is ‘nil’ or not.
      Since such variables often end up acquiring more values over time,
      this convention is not strongly recommended.
 
 ‘...-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 safe or risky; see SeeFile 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.