Next: Subr Arguments, Previous: Preactivation, Up: Advising Functions
アドバイス断片の本体からアドバイスする関数の引数を参照する もっとも簡単な方法は、関数定義で用いているものと同じ名前を使うことです。 これには、元関数の引数の変数名を知る必要があります。
多くの場合、この単純な方法で十分ですが、欠点もあります。 アドバイス内に引数名を直接書き込むために、堅牢ではありません。 関数の元定義が変更されると、アドバイスは動作しません。
他の方法は、アドバイスそのものに引数リストを指定することです。 これは関数の元定義の引数名を知る必要はありませんが、制約もあります。 関数に対するすべてのアドバイスで同一の引数リストを使う必要があります。 なぜなら、すべてのアドバイスに実際に使われる引数リストは、 当該関数のアドバイス断片の最初のものだからです。
より堅牢な方法は、活性にするときに、 つまり、アドバイスを結合した定義を作成するときに 適切なフォームに展開されるマクロを使うことです。 参照用マクロは、関数の引数変数への実引数の分配方法に依存しない 実引数の位置で参照します。 Emacs Lispにおいては、引数の意味は引数リスト内での位置で決まるため、 これは堅牢です。
例を示します。
関数foo
の定義はつぎのとおりであり、
(defun foo (x y &optional z &rest r) ...)
つぎのように呼ばれるとします。
(foo 0 1 2 3 4 5 6)
そうすると、foo
の本体では、
xは0、yは1、zは2、rは(3 4 5 6)
です。
このとき、ad-get-arg
やad-get-args
は、つぎの値を返します。
(ad-get-arg 0) 0 (ad-get-arg 1) 1 (ad-get-arg 2) 2 (ad-get-arg 3) 3 (ad-get-args 2) (2 3 4 5 6) (ad-get-args 4) (4 5 6)
この例では、引数に値を設定できます。
(ad-set-arg 5 "five")
の効果は、6番目の引数を"five"
に変更します。
foo
の本体を実行するまえにこのアドバイスが実行されると、
本体内ではrは(3 4 "five" 6)
になります。
つぎは引数リストを変更する例です。
(ad-set-args 0 '(5 4 3 2 1 0))
foo
の本体を実行するまえにこのアドバイスが実行されると、
foo
の本体内では、
xは5、yは4、zは3、rは(2 1 0)
になります。
これらの引数参照は、実際にはLispマクロとしての実装ではありません。 アドバイス機構で特別に実装してあります。