Next: Obsolete Functions, Previous: Closures, Up: Functions [Contents][Index]
他のライブラリーの関数定義を変更する必要があるとき、またはfoo-function
oのようなフックやプロセスフィルター(process
filter)、または関数を値としてもつ任意の変数またはオブジェクトを変更する必要があるときには、名前つきの関数にはfset
かdefun
、フック変数にはsetq
、プロセスフィルターにはset-process-filter
のように、適切なセッター関数(setter
function)を使用することができます。しかし、これらが以前の値を完全に破棄してしまうのが好ましくない場合もあります。
アドバイス(advice)機能により、関数にアドバイスすることにより、既存の関数定義に機能を追加できます。これは関数全体を再定義するより明解な手法です。
Emacsのアドバイスシステムは2つのプリミティブセットを提供します。コアとなるセットは、変数やオブジェクトのフィールドに保持された関数値にたいするものです(対応するプリミティブはadd-function
とremove-function
です)。もう1つのセットは、名前つき関数の最上位のレイヤーとなるものです(主要なプリミティブはadvice-add
とadvice-remove
です)。
たとえば、プロセスprocのプロセスフィルターの呼び出しをトレースするためには、以下を使用できます:
(defun my-tracing-function (proc string) (message "Proc %S received %S" proc string)) (add-function :before (process-filter proc) #'my-tracing-function)
これにより、そのプロセスの出力は、元のプロセスフィルターに渡される前に、my-tracing-function
に渡されるようになります。my-tracing-function
は元の関数と同じ引数を受け取ります。これを行った場合、以下のようにしてトレースを行わない振る舞いにリバートすることができます。
(remove-function (process-filter proc) #'my-tracing-function)
同様に、display-buffer
という名前つきの関数の実行をトレースしたい場合は、以下を使用できます:
(defun his-tracing-function (orig-fun &rest args) (message "display-buffer called with args %S" args) (let ((res (apply orig-fun args))) (message "display-buffer returned %S" res) res)) (advice-add 'display-buffer :around #'his-tracing-function)
ここで、his-tracing-function
は元の関数のかわりに呼び出され、元の関数(加えてその関数の引数)を引数として受け取るので、必要な場合はそれを呼び出すことができます。出力を確認し終えたら、以下のようにしてトレースしない振る舞いにリバートできます:
(advice-remove 'display-buffer #'his-tracing-function)
上記の例で使用されている引数:before
と:around
は、2つの関数が構成される方法を指定します(これを行うには多くの方法があるからです)。追加された関数も、アドバイス(advice)と呼ばれます。
• Core Advising Primitives: | アドバイスを扱うプリミティブ。 | |
• Advising Named Functions: | 名前つき関数のアドバイス。 | |
• Advice combinators: | アドバイスを構成する方法。 | |
• Porting old advices: | 古いdefadviceを使用したコードの改良。 |