Next: , Previous: , Up: 関数   [Contents][Index]


13.15 コンパイラーへの定義済み関数の指示

あるファイルをバイトコンパイルするとき、コンパイラーが知らない関数について警告が生成されるときがあります(コンパイラーのエラーを参照してください)。実際に問題がある場合もありますが、問題となっている関数がそのコードの実行時にロードされる他のファイルで定義されている場合が通常です。たとえば以前は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-modeshell.el (‘.el’は省略可)の中で定義していることを告げます。コンパイラーは関数がそのファイルで実際に定義されているとみなしてチェックを行いません。

3つ目の引数はオプションでありshell-modeの引数リストを指定します。この例では引数はありません(nilと値を指定しないのは異なる)。それ以外の場合には(file &optional overwrite)のようになります。引数リストを指定する必要はありませんが、指定すればコンパイラーはその呼び出しが宣言と合致するかチェックできます。

Macro: declare-function function file &optional arglist fileonly

ファイルfile内でfunctionが定義されているとみなすようにバイトコンパイラーに告げる。オプションの3つ目の引数arglistt (引数リストが未指定という意味)、または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-functionfileonly引数に非nilを渡すことができる。これはファイルの存在だけをチェックして、その関数の実際の定義はチェックしないことを意味する。これを行うなら引数リストを指定する必要はないが、arglist引数にはtをセットする必要があることに注意(なぜならnilは引数リストが指定されなかったという意味ではなく空の引数リストを意味するため)。