#:g1: INTERLISP: Advisingの紹介

Posted 2014-09-21 12:30:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の264日目です。

INTERLISP: Advisingとはなにか

 INTERLISP: Advisingは、INTERLISPのアドバイス機構です。

パッケージ情報

参考マニュアルInterlisp Reference Manual(1974)

インストール方法

 INTERLISP-10や、Interlisp-Dでは標準の機能です。

試してみる

 アドバイス機構を紹介するのも何回目かという感じですが、今回は、元祖INTERLISPのアドバイスの紹介です。
どうも本当の元祖は、INTERLISPに先行するBBN-LISPみたいですが、1966-1972年のマニュアルでは記載を見付けられなかったので1974年のINTERLISPで確認しました。
試した環境は、pdp-10で稼動するINTERLISP-10です。
REPLを開くとHiと挨拶をしてくれる処理系です(Xmasメッセージもあり)

 さて機能ですが、こんな感じの関数があったとすれば、

(DEFINEQ (matu (X)
           (PRIN1 '>>)
           (SPACES 1)
           (PRIN1 X)
           (TERPRI)))

(matu 8) ;>> >> 8

(ADVISE 'matu 'BEFORE '(PROGN
                        (PRIN1 '..before0:)
                        (TERPRI)))

(ADVISE 'matu 'BEFORE '(PROGN (PRIN1 '..before0:) (TERPRI)))

(advise 'matu '(PROGN (PRIN1 '..before1:) (TERPRI)))

(advise 'matu 'AFTER '(PROGN (PRIN1 '..after0:) (TERPRI)))

(ADVISE 'matu 'AFTER '(PROGN (PRIN1 '..after1:) (TERPRI)))

(ADVISE 'matu 'AROUND '(PROGN (PRIN1 '==>around0:) (TERPRI) * (PRIN1 '>==around0:) (TERPRI)))

(ADVISE 'matu 'AROUND '(PROGN (PRIN1 '==>around1:) (TERPRI) * (PRIN1 '>==around1:) (TERPRI)))

こんな感じにアドバイスをつけると、

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

こんな感じになります。
上記では、アドバイスの順番を指定していないですが、指定しない場合は、後に追加になります。
これは、(first top)/(last bottom end)で前後を指定可能になっています。

(DEFINEQ (zzz () (PRINT 'zzz)))

(ADVISE 'zzz 'BEFORE 'TOP '(PRINT 'hello1)) (ADVISE 'zzz 'BEFORE 'TOP '(PRINT 'hello2))

(zzz) ;>> hello2 ;>> hello1 ;>> zzz ;=> zzz

 面白いのが、関数内の関数にもアドバイスがかけられることで、

(DEFINEQ
  (foo () (PRIN1 'foo) (TERPRI))
  (bar () (PRIN1 'bar)(TERPRI))
  (baz () (PRIN1 'baz)(TERPRI))
  (makanito () (foo) (bar) (baz)))

 こんな感じの定義がある場合、

(ADVISE '((foo baz) IN makanito)
        'AROUND '(PROGN
                  (PRIN1 '>>)
                  (TERPRI)
                  *
                  (PRIN1 '<<)
                  (TERPRI)))

という定義で

(makanito)
;>> >>
;>> foo
;>> <<
;>> bar
;>> >>
;>> baz
;>> <<
;=> NIL

makanito内のfooとbazにアドバイスをかけることができます。
アドバイスの削除は、unadviseで、削除します。

(unadvise 'zzz)

まとめ

 今回は、INTERLISP: Advisingを紹介してみました。
上記のコード例を見てINTERLISPは標準状態の入力時でCommon Lispのようにcaseの変換をしないのに気付いたでしょうか。
大文字小文字はそのまま反映されるため標準関数は大文字で入力する必要があるということで、Common Lispでいうリードテーブルを:preserveモードにした時の挙動と同じということなんですが、一々大文字で入力しなくてもDWIM機能で対話的に修正してくれます(といっても面倒臭いですが)。
ただし、BEFORE、AFTER等の識別子は、DWIM機能が働いてくれなかったりするので気をつける必要があるみたいです。

comments powered by Disqus