Previous: Subr Arguments, Up: Advising Functions


16.10 結合定義

関数には、n個の事前アドバイス(before-advice)、 m個の包囲アドバイス(around-advice)、 k個の事後アドバイス(after-advice)があるとします。 保護したアドバイス断片はないと仮定すると、 関数のアドバイスを実装するために作成される結合定義は つぎのようになります。

     (lambda arglist
       [ [advised-docstring] [(interactive ...)] ]
       (let (ad-return-value)
         before-0-body-form...
              ....
         before-n-1-body-form...
         around-0-body-form...
            around-1-body-form...
                  ....
               around-m-1-body-form...
                  (setq ad-return-value
                        apply original definition to arglist)
               other-around-m-1-body-form...
                  ....
            other-around-1-body-form...
         other-around-0-body-form...
         after-0-body-form...
               ....
         after-k-1-body-form...
         ad-return-value))

マクロはマクロとして再定義します。 つまり、結合定義の先頭にmacroを追加します。

元関数やアドバイス断片のどれかに対話宣言があれば、 対話宣言フォームが入ります。 対話的な基本関数をアドバイスした場合には、 特別な方法を使います。 つまり、基本関数をcall-interactivelyで呼び出して、 基本関数自身が引数を読み取るようにします。 この場合、アドバイスからは引数を参照できません。

各クラスのさまざまなアドバイスの本体フォームは、 それらの指定された順に組み立てられます。 包囲アドバイスl(around-advice l)のフォーム群は、 包囲アドバイスl − 1(around-advice l − 1)の フォームの1つに入ります。

包囲アドバイスのもっとも内側では、

     
     元定義をarglistに適用

しますが、そのフォームは元関数の種類に依存します。 変数ad-return-valueには、その戻り値が設定されます。 この変数はすべてのアドバイス断片から見えるので、 アドバイスした関数から実際に戻るまえに、 これを参照したり変更できます。

保護したアドバイス断片を含むアドバイスした関数の構造も同じです。 唯一の違いは、フォームunwind-protectにより、 アドバイス断片でエラーを起こしたり非ローカル脱出を行っても、 保護したアドバイスが実行されることを保証します。 包囲アドバイスを1つでも保護していると、その結果として、 包囲アドバイス全体が保護されます。