あるファイルをバイトコンパイルするとき、コンパイラーが知らない関数について警告が生成されるときがあります(コンパイラーのエラーを参照してください)。実際に問題がある場合もありますが、問題となっている関数がそのコードの実行時にロードされる他のファイルで定義されている場合が通常です。たとえば以前はsimple.elをバイトコンパイルすると以下のような警告が出ていました:
simple.el:8727:1:Warning: the function ‘shell-mode’ is not known to be defined.
実際のところshell-mode
は(require
'shell)
を実行する関数内のshell-mode
を呼び出す前でのみ使用されるので、shell-mode
は実行時に正しく定義されるでしょう。そのような警告が実際には問題を示さないことを知っているときには警告を抑制したほうがよいでしょう。そうすれば実際に問題があることを示す新しい警告の識別性が良くなります。これはdeclare-function
を使用して行うことができます。
必要なのは問題となっている関数を最初に使用する前にdeclare-function
命令を追加するだけです:
(declare-function shell-mode "shell" ())
これはshell-mode
がshell.el
(‘.el’は省略可)の中で定義していることを告げます。コンパイラーは関数がそのファイルで実際に定義されているとみなしてチェックを行いません。
3つ目の引数はオプションでありshell-mode
の引数リストを指定します。この例では引数はありません(nil
と値を指定しないのは異なる)。それ以外の場合には(file
&optional
overwrite)
のようになります。引数リストを指定する必要はありませんが、指定すればコンパイラーはその呼び出しが宣言と合致するかチェックできます。
ファイルfile内でfunctionが定義されているとみなすようにバイトコンパイラーに告げる。オプションの3つ目の引数arglistはt
(引数リストが未指定という意味)、またはdefun
と同スタイルな正式パラメーターリスト(カッコを含む)のいずれか。arglistを省略した際のデフォルトはnil
ではなくt
。これは引数省略時の非定形な挙動であり、3つ目の引数を指定せずに4つ目引数を与える場合には通常のnil
のかわりに3つ目の引数のプレースホルダーにt
を指定しなければならないことを意味する。オプションの4つ目の引数fileonlyが非nil
なら実際にfunctionが定義されているかではなくfileの存在だけをチェックすることを意味する。
これらの関数がdeclare-function
が告げる場所で実際に宣言されているかどうかを検証するには、check-declare-file
を使用して1つのソースファイル中のすべてのdeclare-function
呼び出しをチェックするか、check-declare-directory
を使用して特定のディレクトリー配下のすべてのファイルをチェックする。
これらのコマンドは、locate-library
で使用する関数の定義を含むはずのファイルを探す。ファイルが見つからなければ、これらのコマンドはdeclare-function
の呼び出しを含むファイルがあるディレクトリーからの相対ファイル名に、定義ファイル名を展開する。
‘.c’や‘.m’で終わるファイル名を指定することにより、プリミティブ関数を指定することもできる。これが有用なのは特定のシステムだけで定義されるプリミティブを呼び出す場合だけである。ほとんどのプリミティブは常に定義されているので、それらについて警告を受け取ることはありえないはずである。
あるファイルがオプションとして外部のパッケージの関数を使う場合もある。declare-function
命令内のファイル名のプレフィクスを‘ext:’にすると、そのファイルが見つかった場合はチェックして、見つからない場合はエラーとせずにスキップする。
‘check-declare’が理解しない関数定義もいくつか存在する(たとえばdefstruct
やその他いくつかのマクロ)。そのような場合はdeclare-function
のfileonly引数に非nil
を渡すことができる。これはファイルの存在だけをチェックして、その関数の実際の定義はチェックしないことを意味する。これを行うなら引数リストを指定する必要はないが、arglist引数にはt
をセットする必要があることに注意(なぜならnil
は引数リストが指定されなかったという意味ではなく空の引数リストを意味するため)。