Lisp本積読解消: 実用Common Lisp | 3.2章 特殊形式: マクロ etc — #:g1

Posted 2017-02-13 17:01:50 GMT

今回は、実用Common Lisp、通称PAIP。名著として名高い本のマクロの解説を読んでみる。

3.2章 特殊形式: マクロ

この本では、まず、特殊形式の仲間としてマクロを解説し、後に正確な定義に近付けているらしく、この章でマクロと特殊形式の違いが解説される。

マクロを書く順序として、

  1. 本当に必要かどうか
  2. 構文を書く(書き出す・考える)
  3. 展開形を考える
  4. 実際にdefmacroで記述する

としていて、本当に必要かどうかまず良く考え、書くとしたら既存の文法に合せるように書くべきであることが説明されている。

実際にマクロを書く例として while を作成するが、最初は、バッククォートを利用しないもので書き、次の段落(逆引用符表記法)でバッククォートを利用したテンプレート作成的な書き方を説明。

他、

でもマクロについての解説あり。

全体的に機能の解説をするついでにコーディングスタイルの話もすることが多いため、余計な解説と情報が多いなという印象。
特殊形式の解説の筈なのに、シーケンス関数の話も混ざっていたり、後の章の話が度々出てきたり、Common Lispの基礎を学ぶのにはこの本はあまり向いていないのではないかと思った。
しかも、コーディングスタイルについては、若干押し付けがましい。
押し付けがましい割には、Norvig先生のコード例も自身のコーディングスタイルに沿っていなかったりする。
また、示されているスタイルは昔からのオーソドックスなものというよりは、Novig先生オリジナルな成分が多目なスタイルに思える。

大著なので、最初に完成した部分と、入門者向けの部分等で統一感がないのかもしれない、と少し思った。

スタイルについては話半分で流しておいて、そこそこ書けるようになって、気になってきたら、Norvig先生がKMP氏と一緒に纏めたスタイル論があるので、別途そちらを参照した方が良いのではないかと思う。

気になった所

局所ローカルマクロ・関数によるシャドウについて

⸨25.14 マクロに関する問題⸩では、3.2章の内容をさらに細かく考察していて、局所ローカルマクロ・関数が展開された関数・マクロをシャドウしてしまう問題についても触れている。
具体的には、下記のような状況だが、

(defun last1 (list)
  (car (last list)))

(defmacro foo (list) `(last1 ,list))

(flet ((last1 (x) x)) (foo '(1 2 3 4)))(1 2 3 4)

これを防ぐには、

(defmacro foo (list)
  `(funcall ,#'last1 ,list))

(flet ((last1 (x) (print x))) (foo '(1 2 3 4))) → 4

と書く必要がある、と解説されている。
実際にはこのように書かれることは殆ど無いが、Common Lispでは、局所ローカルマクロ・関数が多用されないので、スタイル上あまり問題にならないとの説明。

,#'last1というのがそら恐しいが、大域定義を参照するのだから、単に'last1とシンボルで書いてしまえば良いじゃん、と思ってしまった。何か理由があるのだろうか。

  1. #'last1
  2. 'last1
  3. ,#'last1

と書けるが、#'last1と書いてしまっては元の木阿弥。
本書では関数は、#'を付けて書くように統一されているので、'last1ではなく、,#'last1とした、という所だろうか。
もしくは、インライン展開やコンパイラ・マクロへの配慮とか?

局所ローカルマクロ・関数のシャドウ問題への対処は実際には、上記のようにfuncallに分割するようなことはしないで、パッケージ・ロックで防ぐのが一般的だろう。

パッケージ・ロックは、規格外の機能だが大抵の処理系は装備しているので、これを使えばシャドウされたらエラーとすることができる。

たとえば、SBCLであれば、(sb-ext:lock-package "パッケージ")とするだけで良い(もしくはdefpackage:lock Tを指定)

(とはいえLispWorksのように大域的な再定義しかエラーにしてくれない処理系もある……)

記述が古いところがあるので注意

ANSI Common Lispが成立する前に出版された本故に記述が古い所があるdefine-setf-methodspecial-form-p等々)

macroletの解説がない

これだけの大著なのにmacroletの解説がない。
まあ人工知能がメインの本なのでしょうがないのかもしれない。


HTML generated by 3bmd in LispWorks 7.0.0

comments powered by Disqus