Clojure > Archives > 2010/08/06

2010/08/06 18:29:41 UTCshiro
#
これはlegacy macroの厄介さの一端かも RT: @theoria: defmacroにデバッグ機能を付加したところ、Clojureではjarを実行した時にマクロ展開が行われることが判明した。殺す。
#
Clojureがなぜそういう選択をしたかという本当のところは知らないのだけども、一般的にlegacy macro (R6RS macro風にphaseを分けないマクロ) での悩みの種は、コンパイル環境と実行環境が違ってたらどうするか、ということ。
#
legacy macroのマクロ展開ルーチン内に通常の手続きが使われていた場合、マクロ展開時にその手続きが呼べないと困る。でもその手続きはコンパイル時には意図した動作をしてくれないかもしれない (e.g. 実行環境に左右される要素を見て分岐しているような場合)
#
コンパイル時環境と実行環境を完全に同一にできる保障が無いなら、実行環境が確定するまでマクロ展開を遅らせるしかない。
#
R6RS macroでは、Schemeらしい潔癖性でもって、「それならマクロ展開ルーチンから実行時環境を参照するのを禁止しよう」ということになった。マクロ展開ルーチンが見てる世界と実行時に見える世界は別の世界。
#
それはそれで不便なこともあるので悩ましい。
2010/08/06 18:57:30 UTCTheoria
#
なるほど……。
#
普通にjarを実行するだけなら問題にならないのですが、Hadoop向けのMapReduceプログラムの場合、Task毎にmacroexpandが走るんですよね。つまりマクロ展開時間が実行時間に効いてくると……。
#
GaucheでMapReduceが書けたらなぁ……。
2010/08/06 19:06:48 UTCshiro
#
マクロ展開をコンパイル時に行うスイッチとか無いかな。
#
どうしても無理なら、ソースを読んで独自展開しちゃうプリプロセッサを書くとか。
2010/08/06 19:10:55 UTCTheoria
#
definlineがそれっぽい動きをしてくれるかと期待したが、definline自体がdefmacroで定義されているという……
#
結局実行時の前処理からは逃れられない感じがします。プリプロセッサ書かない限り。
2010/08/06 19:51:03 UTCshiro
#
あれ、でもjarロード時にexpandするってことは、その後でclojureコンパイラが走ってJVMコードがon-the-flyで生成されてるってことか? .classファイルを作らずにランタイム生成したJVMコードを実行するのってできたっけ?
#
Java interopマクロなんかもjarロード時に展開してるってのはちょっと考えにくい気がするなあ。
2010/08/06 20:10:09 UTCshiro
#
少なくとも同一ファイル内で定義されてるマクロはコンパイル時に展開されてる
2010/08/06 20:18:37 UTCshiro
#
@theoria 何か、ロード時までマクロ展開を遅延するような特殊な要因があるんでないかい?
2010/08/06 20:31:39 UTCshiro
#
@theoria マクロを別の名前空間で定義して別のclassファイルにコンパイルした場合でも、やっぱりマクロを参照してるコードをコンパイルする時にマクロ展開されるよ?
2010/08/06 20:50:21 UTCshiro
#
ふむ、確かにマクロ展開ルーチンそのものも.classファイルにコンパイルされてるから、何らかの理由で「コンパイル時に、それがマクロであることはわかるんだけど展開ルーチン本体は見えない」という現象が起きれば、ロード時まで展開を遅延することはあるかもしれん。
#
だがそういう現象をどうやって起こせるのかわからない。マクロ生成マクロとかいろいろいじってみたけど、原則、マクロであることがわかるなら展開ルーチンも入手できるはずだしなあ。