RacketのMacroを調べてみる (1)
ちょっときっかけがありましてRacketのMacroを調べてみます
Common Lispのマクロを書くならOn Lisp だとか Practical Common Lisp だとか
読めばよさそうなんですが
Schemeのマクロは流派が分かれててあんまりそれっぽい本はなさそうです
調べてみると Fear of Macros て記事がよさそうなのでこれを読んでみます
適当にメモを書いていきますね
始めたきっかけはこんなことらしいです
- CとかC++を25年くらい使ってた
- Racketを使い始めた
- カッコの多さとか関数型プログラミングにはすぐ慣れた
- あとはMacroとContinuation
- Macroはパターンマッチングを使った簡単なものはすぐわかったけど
- ちょっと難しいことをしようとしたらわからなくなった
- いろいろ調べて、わかってきたところでこの記事を書き始めた
- そしたらいろいろ教えてもらえると思って
Continuationのほうはどうなったんでしょうね
さてどうやって進めていきますか
- Racketやってるんだからsyntax-parse使いたいよね?
Racketは自らプログラミング言語のプラットフォームだとかなんとか
豪語するくらいなのでMacroには力を入れているようです
Schemeのマクロにはsyntax-rulesとかsyntax-caseとかの構文が
用意されていて、もちろんRacketでも使えるようになっているんですけれども
Racketが独自に拡張したのがsyntax-parseということらしいです
- でもいきなりそこからはやらないよ
- まずはsyntax objectとそれを変換する関数であるtransformerから始める
- そこがわかれば難しく見えたマクロのしくみがわかってくる
- そこでsyntax-caseをやればパターンマッチのありがたさが見えてくる
- define-syntax-ruleはただの短縮形だ
- ここまでくればかなりのMacroが書けるようになる
- でも、いわゆるanaphoric ifはどう書けばいい?
anaphoric ifっていうのは例えば (aif (cdr l) (car it) '())
って
書くとit
が (cdr l)
の結果を覚えててくれる、っていうちょっと
便利版ifのことです
Schemeのマクロはhygieneといって、マクロの中で使った変数名と
マクロの外の変数名がカブっちゃっても大丈夫なようになってます
おかげでたいていは楽できるんですが、あえてマクロの外側に影響を
あたえようとするとちょっと技が必要になってきます
- ここまできたらエラーのときに親切なメッセージを出してくれるようにしたいよね
- Racketの関数に、契約と型がつけられて、わかりやすいメッセージが出せるように
- Racketのマクロにはsyntax-parseがあるのさ
今日はここまで
達成!