#:g1: Lucid CL: Adviceの紹介

Posted 2014-10-19 15:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の293日目です。

Lucid CL: Adviceとはなにか

 Lucid CL: Adviceは、Lucid CLのアドバイス機構です。

パッケージ情報

パッケージ名Lucid CL: Advice
ドキュメントLiquid CL: 6.3 The Advice Facility

インストール方法

 Lucid CL/Liquid CLでは標準で使えます。LCLパッケージで定義されていますが、CL-USERからも使えるようになっています。

試してみる

 今回もこれまでのアドバイス機構の紹介と同じ例ですが、Lucid CL版で他と違っているのは、基本的にaroundのみで、それを他のアドバイスの内側に追加するか、外側に追加するかを指定するという所です。
動作的には、aroundしかないのでbeforeに相当するものは、最後にadvice-continueし、afterは、最初にadvice-continueしてから後の処理を追加する、という感じになります。
動作的にと書いたのは、ややこしいことに、:insideの別名として:after、:outsideの別名として:beforeが使えるからなのですが、:before/:afterで考えると混乱するので、ここでは、:inside/:outsideのみで紹介します。
ちなみに、指定しなければデフォルトで:outsideを指定したことになります。
尚、Lucid CLのアドバイスも定義する順番で動作が変わるので定義順が重要になっています。

(defun matu (x)
  (format t "~&>>~A<<~%" x))

(matu 8) ;>> >>8<< ;=> NIL


(defadvice (matu around0) (n)
  (prog2
    (write-line "around0 ==>")
    (advice-continue n)
    (write-line "around0 <==")))

(defadvice (matu around1 (:outside around0)) (n) (prog2 (write-line "around1 ==>") (advice-continue n) (write-line "around1 <==")))

(defadvice (matu before0 (:inside around0)) (n) (write-line "before0:") (advice-continue n))

(defadvice (matu before1 (:outside before0)) (n) (write-line "before1:") (advice-continue n))

(defadvice (matu after0 (:inside around0)) (n) (prog1 (advice-continue n) (write-line "after0:")))

(defadvice (matu after1 (:outside after0)) (n) (prog1 (advice-continue n) (write-line "after1:")))

(matu 8) ;>> around1 ==> ;>> around0 ==> ;>> before1: ;>> before0: ;>> >>8<< ;>> after0: ;>> after1: ;>> around0 <== ;>> around1 <== ;=> NIL

 また、マクロにもアドバイスは定義可能です。

(defmacro mydefun (name (&rest args) &body body)
  `(defun ,name (,@args) ,@body))

(defadvice (mydefun inline) (form env) (destructuring-bind (def name args &body body) form (declare (ignore def args body)) `(progn (declaim (inline ,name)) ,(advice-continue form env))))

(mydefun foo (n) n) ;===> (PROGN (DECLAIM (INLINE FOO)) (DEFUN FOO (N) N))

 他、アドバイスの削除には、remove-adviceが使え、アドバイスのdescribeには、describe-adviceが定義されています。

(describe-advice 'matu)
;>> Advice AROUND1: #<Interpreted-Function (:ADVICE MATU AROUND1) C0E767>
;>>   Advice AROUND0: #<Interpreted-Function (:ADVICE MATU AROUND0) C0E717>
;>>     Advice AFTER1: #<Interpreted-Function (:ADVICE MATU AFTER1) C0E6C7>
;>>       Advice AFTER0: #<Interpreted-Function (:ADVICE MATU AFTER0) C0E677>
;>>         Advice BEFORE1: #<Interpreted-Function (:ADVICE MATU BEFORE1) C0E627>
;>>           Advice BEFORE0: #<Interpreted-Function (:ADVICE MATU BEFORE0) C0E4B7>
;>>             Original definition: #<Interpreted-Function (NAMED-LAMBDA MATU (X) (BLOCK MATU (FORMAT T "~&>>~A<<~%" X))) BF7AB7>
;=> NIL

まとめ

 今回は、Lucid CL: Adviceを紹介してみました。
MIT Lispマシン系統とはちょっと違った方式でなかなか面白いです。

comments powered by Disqus