Next: , Previous: , Up: Advising Functions   [Contents][Index]


12.10.2 名前つき関数にたいするアドバイス

アドバイスは名前つき関数やマクロにたいして使用するのが一般的な使い方です。これは単にadd-functionを使用して以下のように行うことができます:

(add-function :around (symbol-function 'fun) #'his-tracing-function)

しかし、かわりにadvice-addadvice-removeを使うべきです。この別の関数セットは名前つき関数に適用されるアドバイス断片を操作するためのもので、add-functionと比較して以下の追加機能があります。まず、これらはマクロおよびオートロードされた関数を扱う方法を知っています。次に、describe-functionにたいして、追加されたアドバイスと同様に、元のドキュメント文字列を維持します。さらに、関数が定義される前でも、アドバイスの追加と削除ができます。

既存の関数全体を再定義せずに既存の呼び出しを変更するために、advice-addが有用になります。しかしその関数の既存の呼び出し元は古い振る舞いを前提としているかもしれず、アドバイスによりその振る舞いが変更されたときに正しく機能しないかもしれないので、これはソー内スのバグにもなり得ます。アドバイスはデバッグを難しくする可能性もあります。デバッグを行う人はその関数がアドバイスにより変更されたことに気づかなかったり、失念しているかもしれません。

これらの理由により、他の方法で関数の振る舞いを変更できない場合に備えるために、アドバイスの使用は控えるべきです。フックを通じて同じことが行えるならフック(Hooksを参照)の使用が望ましい方法です。特定のキーが行う何かを変更したいだけなら、新しいコマンドを記述して、古いコマンドのキーバインドを新しいコマンドにリマップ(Remapping Commandsを参照)するのが、おそらくより良い方法です。特にEmacs自身のソースファイルは、Emacs内の関数をアドバイスするべきではありません(現在のところこの慣習にはいくつかの例外があるが、わたしたちはこれを改善しようと思っている)。

スペシャルフォーム(Special Formsを参照)はアドバイスできませんが、マクロは関数と同じ方法でアドバイスできます。もちろんこれはすでにマクロ展開されたコードには影響しないため、マクロ展開前にアドバイスが確実にインストールされる必要があります。

プリミティブ(What Is a Functionを参照)にアドバイスするのは可能ですが、2つの理由により通常は行うべきではありません。1つ目の理由はいくつかのプリミティブがアドバイスのメカニズム内で使用されているため、それらにたいしてアドバイスを行うと無限再帰が発生するからです。2つ目の理由は多くのプリミティブがCから直接呼び出されていて、そのような呼び出しはアドバイスを無視するからです。したがってプリミティブにたいしてアドバイスの使用を控えることにより、ある呼び出しはアドバイスにしたがい(Lispコードから呼びだされたため)、他の呼び出しではアドバイスにしたがわない(Cコードから呼び出されたため)という混乱した状況を解決できます。

Function: advice-add symbol where function &optional props

名前つき関数symbolにアドバイスfunctionを追加する。wherepropsadd-function(Core Advising Primitivesを参照)のときと同じ意味をもつ。

Function: advice-remove symbol function

名前つき関数symbolからアドバイスfunctionを取り除きます。functionにアドバイスのnameを指定することもできます。

Function: advice-member-p function symbol

名前つき関数symbol内にすでにアドバイスfunctionがある場合は、非nilをreturnします。functionにアドバイスのnameを指定することもできます。

Function: advice-mapc function symbol

名前つき関数symbolにすでに追加されたすべての関数にたいして、functionを呼び出します。functionは2つの引数、アドバイス関数と、そのプロパティーで呼び出されます。