Schemeのマクロには大きく分けて
- R5RSマクロ:パターンマッチによるマクロ
- レガシーなマクロ:LISPに伝統的なマクロ
があるとid:yagiey:20100126:1264525307で紹介した。
今回は後者に関して。
R5RSマクロは以下のようなマクロを実現できない、もしくは実現が困難だという(p271)。
- 故意に変数衝突を許す不健全なマクロ
- 新たな名前の変数を作り出すマクロ
- 複雑な変換処理が必要なマクロ
まず1つ目に関して、
プログラミング言語は、少数の基本機能を自由に組み合わせて作られるべきである
(p267)というのがSchemeのポリシーで、そのためには
抽象化の破れをもたらす変数名の衝突を避けなければなりません
(p267)ということでR5RSマクロが導入された。つまり、変数名が衝突しないようにするしくみがR5RSマクロなので、変数を衝突させるのは無理だと。
マクロを利用する側が、マクロ内で束縛した変数を参照したい場合は、マクロを利用する側が変数名を与えてやるのがScheme流だと。
gosh> (define-syntax aif (syntax-rules () ((aif var test then) (let ((var test)) (if var then))))) #<undef> gosh> (aif it (member 3 '(1 2 3 4 5)) it) (3 4 5) gosh> (aif it (member 6 '(1 2 3 4 5)) it) #<undef>
こんな感じ。
ちなみにこのaifはOn Lispで紹介されているaifをScheme流に改良したものらしい。
3つ目に関しては、
使える道具がパターンマッチと再帰しか無いため、複雑な変換を書こうとすると冗長になりがち
とのこと。
さて、残る2つ目に関しては、「構造体定義の際にスロットアクセス手続きを自動で定義したい」とかなんかよくわからない例が書いてあったけど、要はR5RSマクロでは無理だと。
ということで、「新たな変数名を作り出す」という要請に対しての解決策という形で紹介される伝統的なマクロを次回。