変数定義(variable
definition)とは、そのシンボルをグローバル変数として使用する意図を表明する構文です。これには以下で説明するスペシャルフォームdefvar
やdefconst
が使用されます。
変数宣言は3つの目的をもちます。1番目はコードを読む人にたいして、そのシンボルが特定の方法(変数として)使用されることを意図したものだと知らせることです。2番目はLispシステムにたいしてオプションで初期値とドキュメント文字列を与えて、これを知らせることです。3番目はetags
のようなプログラミングツールにたいして、その変数が定義されている場所を見つけられるように情報を提供することです。
defconst
とdefvar
の主な違いは、人間の読み手に値が変更されるかどうかを知らせることにあります。Emacs
Lispは実際に、defconst
で定義された変数の値の変更を妨げません。この2つのフォームの特筆すべき違いは、defconst
は無条件で変数を初期化して、defvar
は変数が元々voidのときだけ初期化することです。
カスタマイズ可能な変数を定義する場合は、defcustom
を使用するべきです(これはサブルーチンとしてdefvar
を呼び出す)。カスタマイゼーション変数の定義を参照してください。
このスペシャルフォームは変数としてsymbolを定義する。symbolが評価されないことに注意。シンボルはdefvar
フォーム内に明示的に表記して定義される必要がある。この変数は特別だとマークされて、これは常に変数がダイナミックにバインドされることを意味する(変数のバインディングのスコーピングルールを参照)。
valueが指定されていてsymbolがvoid(たとえばこのシンボルがダイナミックにバインドされた値を持たないとき。変数がvoidのときを参照)ならvalueが評価されて、その結果がsymbolにセットされる。しかしsymbolがvoidでなければ、valueは評価されずsymbolの値は変更されない。valueが省略された場合は、いかなる場合もsymbolの値は変更されない。
たとえnil
であっても値を指定することにより、その変数は特別だと永続的にマークされることに注意。一方でvalueが省略されると変数はローカル(カレントのレキシカルスコープまたはトップレベルにあればファイル)でのみ特別だとマークされる。これはバイトコンパイルの警告を抑止するために有用。コンパイラーのエラーを参照のこと。
symbolがカレントバッファー内でバッファーローカルなバインディングをもつ場合、defvar
はデフォルト値に作用する。デフォルト値はバッファーローカルなバインディングではなく、バッファーにたいして独立である。デフォルト値がvoidのときはデフォルト値をセットする。バッファーローカル変数を参照のこと。
すでにsymbolがletバインドされている(たとえばlet
フォーム内にdefvar
がある)場合には、set-default-toplevel-value
と同じようにdefvar
はトップレベルの値をセットする。letバインディングの構文を抜けるまでバインディングの効果は持続する。変数のバインディングのスコーピングルールを参照のこと。
C-M-x (eval-defun
)、またはEmacs LispモードでC-x C-e
(eval-last-sexp
)によりトップレベルのdefvar
を評価する際には、これら2つのコマンドの特別な機能はその値がvoidであるかテストすることなく、その変数を無条件にセットする。
引数doc-stringが与えられたら、それは変数にたいするドキュメント文字列を指定する(そのシンボルのvariable-documentation
プロパティに格納される)。ドキュメントを参照のこと。
以下にいくつか例を示す。これはfoo
を定義するが初期化は行わない:
(defvar foo) ⇒ foo
以下の例はbar
の値を23
に初期化してドキュメント文字列を与える:
(defvar bar 23 "The normal weight of a bar.") ⇒ bar
defvar
フォームはsymbolをリターンするが、これは通常は値が問題にならないファイル内のトップレベルで使用される。
値をもたないdefvar
のより詳細な使用例はLocal defvar exampleを参照のこと。
このスペシャルフォームはある値でsymbolを定義して、それを初期化する。これはコードを読む人に、symbolがここで設定される標準的なグローバル値をもち、ユーザーや他のプログラムがそれを変更すべきではないことを知らせる。symbolが評価されないことに注意。定義されるシンボルはdefconst
内に明示的に記されなければならない。
defvar
と同様、defconst
は変数を特別 —
この変数が常にダイナミックにバインドされているという意味 — であるとマークする(変数のバインディングのスコーピングルールを参照)。加えてこれはその変数を危険であるとマークする(ファイルローカル変数を参照)。
defconst
は常にvalueを評価して、その結果をsymbolの値にセットする。カレントバッファー内でsymbolがバッファーローカルなバインディングをもつなら、defconst
はデフォルト値ではなくバッファーローカルな値をセットする(しかしdefconst
で定義されたシンボルにたいしてバッファーローカルなバインディングを作らないこと)。
defconst
の使い方の例は、Emacsのfloat-pi
—
(たとえインディアナ州議会が何を試みようと)何者かにより変更されるべきではない数学定数piにたいする定義である。しかし2番目のdefconst
の例のように、これは単にアドバイス的なものである。
(defconst float-pi 3.141592653589793 "The value of Pi.") ⇒ float-pi
(setq float-pi 3) ⇒ float-pi
float-pi ⇒ 3
警告:
変数がローカルバインディングをもつとき(let
により作成された、または関数の引数の場合)に、スペシャルフォームdefconst
またはdefvar
を使用すると、これらのフォームはグローバルバインディングではなく、ローカルバインディングをセットします。これは通常は、あなたが望むことではないはずです。これを防ぐには、これらのスペシャルフォームをファイル内のトップレベルで使用します。この場所は通常、何のローカルバインディングも効果をもたないので、その変数にたいするローカルバインディングが作成される前にファイルがロードされることが確実だからです。