Next: , Previous: Void Variables, Up: Variables


10.5 グローバル変数を定義する

スペシャルフォームdefconstdefvar変数定義を使って、 シンボルをグローバル変数として使う意図を表明できます。

Emacs Lispでは、定義には3つの目的があります。 まず、コードを読む人向けに、特定のシンボルを(変数として)特定目的に 使う意図があることを知らせます。 第2に、Lispシステムに対しては、値と説明文字列を提供して これらのことを伝えます。 第3に、プログラム内の関数や変数のデータベースを作成する etagsmake-docfileなどのユーティリティに情報を提供します。

defconstdefvarの違いは、主に好みの問題であり、 値が変更されるかどうかを人に伝えます。 Emacs Lispは、defconstdefvarの宣言に基づいて 変数の使い方を制限することはしません。 しかしながら、初期化に関しては違いがあります。 defconstは無条件に変数を初期化しますが、 defvarは変数が空である場合にのみ初期化します。

— Special Form: defvar symbol [value [doc-string]]

このスペシャルフォームは、symbolを変数として定義し、 初期値や説明文字列を設定する。 この定義は、コードを読む人向けに、 値を設定したり変更する変数としてsymbolを使うことを伝える。 symbolは評価されないことに注意。 定義するシンボルは、defvarに明示的に現れる必要がある。

symbolの値が空でありvalueを指定してあると、 defvarvalueを評価し、その結果をsymbolに設定する。 しかし、symbolにすでに値があれば(つまり、空でなければ)、 valueをまったく評価せず、symbolの値も変更しない。 valueを省略した場合、symbolの値をいっさい変更しない。

symbolにカレントバッファでバッファローカルな束縛がある場合には、 defvarはデフォルト値に作用する。 それは、バッファには独立であり、現在の(バッファローカルな)束縛ではない。 defvarは、デフォルト値が空の場合にデフォルト値を設定する。 see Buffer-Local Variables

emacs-lispモードにおいてC-M-xeval-defun)でトップレベルの フォームdefvarを評価すると、 eval-defunの特別な機能により、 変数の値が空かどうかを調べずに無条件に変数に設定する。

doc-stringがあれば、それは変数の説明文を指定する。 (説明文を指定できるのは、変数定義の主な利点の1つである。) 説明文はシンボルの属性variable-documentationに格納する。 Emacsのヘルプ関数(see Documentation)は、この属性を調べる。

doc-stringの最初の文字が‘*’であると、 この変数をユーザーオプションと考えることを意味する。 これにより、ユーザーはコマンドset-variableedit-optionsを 使って簡単に変数を設定できる。 しかしながら、ユーザーオプションの変数には、 defvarではなくdefcustomを使ったほうがよく、 そうすればカスタマイズ情報を指定できる。 see Customization

いくつか例をあげる。 つぎのフォームはfooを定義するが初期化はしない。

          (defvar foo)
                foo

つぎの例は、barの値を23に初期化し、説明文字列を与える。

          (defvar bar 23
            "The normal weight of a bar.")
                bar

つぎの例は、barの説明文字列を変更し、 この変数をユーザーオプションにする。 しかし、barにはすでに値が設定してあるので、 その値は変更しない。 (さらに(1+ nil)は評価するとエラーになるが、 評価されないのでエラーはない。)

          (defvar bar (1+ nil)
            "*The normal weight of a bar.")
                bar
          bar
                23

つぎの例は、スペシャルフォームdefvarに等価な式である。

          (defvar symbol value doc-string)
          ==
          (progn
            (if (not (boundp 'symbol))
                (setq symbol value))
            (if 'doc-string
              (put 'symbol 'variable-documentation 'doc-string))
            'symbol)

フォームdefvarsymbolを返すが、 通常このフォームはファイルのトップレベルで使われ、そこでは値は関係ない。

— Special Form: defconst symbol [value [doc-string]]

このスペシャルフォームは、symbolを変数として定義し初期化する。 この定義は、コードを読む人向けに、 symbolはこれ以降標準のグローバル値を持ち、 ユーザーや他のプログラムが変更すべきでないことを伝える。 symbolは評価されないことに注意。 定義するシンボルは、defconstに明示的に現れる必要がある。

defconstは、valueがあればつねにvalueを評価し、 その結果をsymbolに設定する。 symbolにカレントバッファのバッファローカルな束縛がある場合には、 defconstはデフォルト値を設定し、 バッファローカルな値にではない。 (しかし、defconstで定義するシンボルには、 バッファローカルな束縛を作るべきではない。)

つぎの例では、piは、(インディアナ州立法府はいうにおよばず) だれも変更すべきではないと考えられる定数である。 しかし、2番目のフォームからわかるように、これは単に助言でしかない。

          (defconst pi 3.1415 "Pi to five places.")
                pi
          (setq pi 3)
                pi
          pi
                3
— Function: user-variable-p variable

この関数は、variableがユーザーオプション、つまり、 カスタマイズのためにユーザーが設定することを意図した変数であると、 tを返し、さもなければnilを返す。 (ユーザーオプション向け以外の変数は、Lispプログラムの内部目的用にあり、 それらについてユーザーが知る必要はない。)

ユーザーオプション変数は、 属性variable-documentationの最初の文字で他の変数と区別される。 その属性が存在して文字列であり、最初の文字が‘*’であれば、 その変数はユーザーオプションである。

ユーザーオプション変数に属性variable-interactiveがあると、 コマンドset-variableはその属性値を使って、 変数の新しい値の読み取りを制御します。 この属性値は、interactiveの引数(see Using Interactive) のように使われます。 しかしながら、この機能はdefcustom(see Customization)により ほとんど廃れています。

警告: 変数にローカル束縛があるときに スペシャルフォームdefconstdefvarを使うと、 ローカル束縛の値を変更し、グローバル束縛は変更しない。 これは望む効果ではない。 これを防ぐには、これらのスペシャルフォームはファイルのトップレベルで使う。 そうすれば、普通は有効なローカル束縛はない。 さらに、変数のローカル束縛を作るまえに、 確実にファイルをロードしておく。