Lisp本積読解消: Artificial Intelligence Programming 2nd ed. | 2. Macros and Read-Macros — #:g1

Posted 2017-02-14 17:24:27 GMT

今回は、Artificial Intelligence Programming 2nd ed.を読む。 2013年にAmazonで565円位で購入。
第一版の方は、人工知能プログラミング / 日本コンピュータ協会として翻訳もされているらしいが、この本は何故かAmazonでは取り扱いがない。
第一版の方は出版が1981年ということもあるので、LispはCommon Lisp以前の方言だと思われる。

第二版は、1987年の書籍。
人工知能プログラミングの本だが、半分位はCommon Lispの解説があり、PAIPと似たような構成。というかLispの人工知能本は、第一部Common Lisp、第二部人工知能という構成が殆どで、この本もそのようになっている。

著者は、Eugene Charniak、Christpher K. Riesebeck、Drew V. McDermott、James R. Meehan各氏でLisp界隈では有名な方々。

制御構文の詳しい解説もされていない2章の時点でマクロとリーダーマクロの解説を始めるというのは、なかなか珍しいと思った。
しかも、リーダーマクロの解説が先。リーダーマクロの解説の題材もバッククォートを展開する関数を定義して、動きを観察したり、動作をいじってみたりする。
set-macro-characterの使い方なども解説される。

リーダーマクロの次に通常のマクロの解説になるが、バッククォートの詳細は理解しているので、そちらの解説はなし。
マクロ学習の題材としては、letの作成が取り上げられる。

次に、repeatというdotimesのようなマクロをお題にして、マクロ変数の捕捉問題と、多重評価問題を解説する。
この解説の中で、変数捕捉回避の方法として、gensymを使った方法とは別に、thunkを使った方法が解説される。

(defmacro repeat (n &body body)
  `(let ((thunk (lambda () ,@body))
         (cnt ,n))
     (loop 
      (when (>= 0 cnt) (return))
      (funcall thunk)
      (decf cnt))))

更に、このrepeatの場合は、下請け関数にthunkを渡すように展開してしまうことも可能であることが示される。

(defmacro repeat (n &body body)
  (repeat* ,n (lambda () ,@body)))

この辺りは類似の本には見られない解説で面白い。
一応、クロージャーで変数捕捉を回避する方は、関数呼び出しが発生するのでベタに展開するマクロより効率は落ちるという説明もされている。

下請け関数に全部任せてしまうのは、最近では、call-withスタイルとも呼ばれ、Google Common Lispスタイルガイドでも紹介されているものだが、結構昔からあるんだなあと感心

なお、thunkもインライン化されたりコンパイラが優秀ならば、ベタなマクロと同じ効率になることもあるので、一概には効率が落ちるともいえないと思う。

といっても、まあ効率重視の局面ではベタに書くのが良いのだろう(二転三転)

そして、let特殊変数スペシャル変数専用の結合束縛構文版を作成する。これは後の章で更に込み入ったものとなる(最終的にはletfのようなものになる)

気になった所

題材は面白いんだけれども、練習問題を解くのは結構難しい気がした。
機転が利く人は前提知識がなくても解けるのかもしれないが、解けなくても、自分なりに考えた上で解答を見て動作を確認すれば、へえと感心するような類の問題が多い気がする。 (なお、回答は巻末に纏まっている)


HTML generated by 3bmd in LispWorks 7.0.0

comments powered by Disqus