#:g1: リーダーマクロでリード時切り分け

Posted 2012-12-06 15:00:00 GMT

今回は、リーダーマクロでリード時のコードの切り分けの実現です。

リード時切り分け

そもそもリード時でコードを切り換えるのって便利なのか、という話もあるかもしれませんが、これが結構Common Lispを含むMacLISP系方言では活躍しています。そもそも、ディスパッチマクロ文字は、当初処理系の切り替えの為に登場してきたようなのですが、登場当時の70年代後半は、MacLISP系では、MacLISP・Lisp machine Lisp・NILと、大体同じだけど微妙に違う方言がMITという同じ場所を中心に開発されていました。
やはり、共通するものを完全に別個に開発するのは無駄だとなったのか、

(defun foo ()
  (print #m 'maclisp
         #n 'nil
         #q 'lisp-machine))
のような感じで、#処理系を表わす一文字 に続く式は該当する処理系でしか読み取られない、というものが考案され、利用されていたようです。MはMacLISP、NはNIL、Qは何故かLispマシン。

『#+・#-』

初期の切り分けの試みがある程度成功したのか、それとも、より一般的な仕組みを考えついてしまったのか、しばらくして、『#一文字』 方式より一般的な仕組みである、『#+・#-』が考案された様です。基本的に現在のCommon Lispと同じで、*features*という変数にシンボルのリストが格納されていて、それが存在する/しないで読み取るか否かを制御します。上述の例をこれで記述すると
(defun foo ()
  (print #+maclisp 'maclisp
         #+nil 'nil
         #+lispm 'lisp-machine
         #-(or maclisp nil lispm) 'otherwise))
という風になります。『#一文字』だと#+の『読み取りたい』という表現しかできませんが、#-で否定の表現ができるところが進歩です。それに加えて、and・or・notで演算する機能も加えられています。
ちなみに、現在Common Lispの常套句で#+nilをコメント代わりに使う、というのがありますが、上記のように実際にNILという処理系があったのだということを思い出し、歴史ロマンに思いを馳せるのも良いでしょう。
ということで練習問題です。

その他の例

前回に引き続きの紹介ですが、1980年代に存在した、LSB(Layered System Building)(PDF)という方言の上に共通言語を構築する試みでは、
{(only-for 処理系) ...}
{(exept-for 処理系) ...}
のように、{}の中で、only-for・except-forを使い、{}の中身を読んだり読まなかったりできたようです。

まとめ

Common Lispでも過去のMacLISPや、Lisp machine Lispの30年以上前のソースコードをいまだに共通で利用することが可能なのですが、それもこのリード時の切り分け機能が共通なためです。もちろん、このような極端な利用だけでなく、処理系依存の機能や、プラットフォーム依存の箇所の切り分けに大活躍していて、ソースコードの共通利用という点では、美しくはないものの、かなりの実績と汎用性があります。
以上、今回は、読み取り時のコードの切り分けをするリーダーマクロについて解説してみました。9回目からは、リーダーマクロの用法の殆どを占める略語やリテラル表現を4回位に分けて解説します。
次回は、@mgikenさんによるArcでのリーダーマクロです。

comments powered by Disqus