2229a2f284 2012-07-07 kinaba: @macro レイヤをどう実装するべきか 2229a2f284 2012-07-07 kinaba: 2229a2f284 2012-07-07 kinaba: - 「マクロレイヤは実行時レイヤの先に実行される」が 2229a2f284 2012-07-07 kinaba: - 「マクロ定義内で実行時関数を(構文木の操作のためなどに)使えると便利である」 2229a2f284 2012-07-07 kinaba: - 「といって、特に関数内マクロなどについて、実行時のスコープが定まるのを待ってから 2229a2f284 2012-07-07 kinaba: 毎回関数実行のたびにマクロ展開していると遅い」 2229a2f284 2012-07-07 kinaba: 2229a2f284 2012-07-07 kinaba: ざっと調べた結果。 2229a2f284 2012-07-07 kinaba: 普段スコープ内マクロとか全く使わないので間違ってる恐れが多々あるので注意。 2229a2f284 2012-07-07 kinaba: 2229a2f284 2012-07-07 kinaba: Common Lisp 2229a2f284 2012-07-07 kinaba: http://www.lispworks.com/documentation/HyperSpec/Body/m_defmac.htm 2229a2f284 2012-07-07 kinaba: http://www.lispworks.com/documentation/HyperSpec/Body/03_abaa.htm 2229a2f284 2012-07-07 kinaba: 2229a2f284 2012-07-07 kinaba: - トップレベルの defmacro の body は compile 時に実行できなくてはいけない 2229a2f284 2012-07-07 kinaba: - トップレベル defmacro の出現以降の式は全て一度に compile 時展開される (must?) 2229a2f284 2012-07-07 kinaba: - (eval-when (:compile) (require ...)) 的なかんじの指定をすることで 2229a2f284 2012-07-07 kinaba: コンパイル時にライブラリ関数をimport等はできるので、それでまあ実行時間数もわりと 2229a2f284 2012-07-07 kinaba: コンパイル時にも使える 2229a2f284 2012-07-07 kinaba: 2229a2f284 2012-07-07 kinaba: - lexical scope 内での defmacro は環境も普通にキャプチャできるし普通に"実行時"に展開される。 2229a2f284 2012-07-07 kinaba: すなわち関数本体の実行は、というか書く式 "form" の、eval はまず macro なら展開してから 2229a2f284 2012-07-07 kinaba: eval、というステップを踏む 2229a2f284 2012-07-07 kinaba: 2229a2f284 2012-07-07 kinaba: たいていの「コンパイルできる」普通のマクロは速く処理できて、 2229a2f284 2012-07-07 kinaba: 実行時環境キャプチャするようなこともしたければ自由に出来るけど遅くていいやという感じか。 2229a2f284 2012-07-07 kinaba: 2229a2f284 2012-07-07 kinaba: 2229a2f284 2012-07-07 kinaba: R6RS 2229a2f284 2012-07-07 kinaba: http://practical-scheme.net/wiliki/wiliki.cgi?R6RS%3a%E7%BF%BB%E8%A8%B3%3aR6RS%3a10%20Expansion%20process 2229a2f284 2012-07-07 kinaba: 2229a2f284 2012-07-07 kinaba: 全部コンパイル時にやる。 2229a2f284 2012-07-07 kinaba: 実行時束縛 (define や (let や (lambda は、hygenic 性のために変数束縛であることは記録されるし、 2229a2f284 2012-07-07 kinaba: あと微妙にマクロ展開の評価順序も変えるけど、基本的にはマクロ展開器はこの辺の special form を素通りして 2229a2f284 2012-07-07 kinaba: いきなりコンパイル時に中まで展開をかける。以降、実行時はまったく展開は起きない。 2229a2f284 2012-07-07 kinaba: 2229a2f284 2012-07-07 kinaba: - lexical scope のキャプチャは? 2229a2f284 2012-07-07 kinaba: spec ではどういう扱いなのかいまいちよくわからない。 2229a2f284 2012-07-07 kinaba: - Gauche はコンパイル時に解決されるものだけは解決してくれた。 2229a2f284 2012-07-07 kinaba: (lambda (x) 2229a2f284 2012-07-07 kinaba: ... (let-syntax ... x ...) ... 2229a2f284 2012-07-07 kinaba: この x は stray local variable エラーになるけど 2229a2f284 2012-07-07 kinaba: (let ((x 1)) 2229a2f284 2012-07-07 kinaba: ... (let-syntax ... x ...) ... 2229a2f284 2012-07-07 kinaba: は行ける 2229a2f284 2012-07-07 kinaba: 2229a2f284 2012-07-07 kinaba: 現実的で妥当だと思うけどスコープの概念が錯綜している感が初見ではして 2229a2f284 2012-07-07 kinaba: (といっても深く考えるとそうでもないように思えてくるけど)すこし慣れにくいかも