(内部に束縛を含むようなキーマップなどの)複雑な値を保持する変数を
定義し初期化するときには、つぎのように、
値の計算全体をdefvar
の内部に入れておくのが最良です。
(defvar my-mode-map (let ((map (make-sparse-keymap))) (define-key map "\C-c\C-a" 'my-command) ... map) docstring)
この方法には、いくつかの利点があります。
まず、ファイルのロード中にユーザーが中断した場合、
変数は初期化されないか正しく初期化されるかのいずれかであり、
その中間状態ということはありません。
第2に、変数をすでに初期化したあとにファイルをロードし直しても、
変数を変更しません。
(キーをバインドし直すなどの)内容の一部を変更するために
ユーザーがフックを実行した場合などには、これは重要です。
第3に、C-M-xでフォームdefvar
を評価すると、
マップを完全に初期化し直せます。
フォームdefvar
の内側に多くのコードを置くことには、欠点が1つあります。
変数の名前を指定した行から説明文字列が離れすぎてしまうことです。
つぎのようにしてこれを安全に防げます。
(defvar my-mode-map nil docstring) (if my-mode-map nil (let ((map (make-sparse-keymap))) (define-key my-mode-map "\C-c\C-a" 'my-command) ... (setq my-mode-map map)))
これには、defvar
の内側に初期化を入れたときと同じ利点がありますが、
変数を再初期化するには、各フォームそれぞれについて
C-M-xを打つ必要があります。
しかし、つぎのようなコードは書かないでください。
(defvar my-mode-map nil docstring) (if my-mode-map nil (setq my-mode-map (make-sparse-keymap)) (define-key my-mode-map "\C-c\C-a" 'my-command) ...)
このコードでは、変数を設定してから変更しますが、
それを複数の手順で行います。
setq
の直後にユーザーが中断すると、
変数は正しく初期化されておらず、空でもnil
でもありません。
こうなったときにファイルを再ロードしても変数を初期化できません。
変数は不完全な状態のままです。