DSL / Macros


DSL

マクロ

一言要約

マクロは難しく慎重に扱わなければならないが、Parse Tree Manipulationのような有用なケースにおいて強力に威力を発揮する。(そんなケースは現状あまりないけどね)

要約

マクロはLispにおいて、DSLを実践する上で中心的役割を果たす。

ほとんどの人は何かしらのマクロに出会っており、Cのマクロはその代表例である。

Cのマクロの仕組みは、パラメータつきのテキスト置換である。 例えば以下のようなマクロを定義し、

#define assert(expr) if (!(expr)) abort()

この式が記述されていると、

assert(c > 5);

以下の式に置き換えられる。

if (!(c > 5)) abort();

プログラミングの初期の頃はよく使われていたが、分かりづらいエラーをすぐに引き起こしてしまうため、最近はあまり使われない。

Cのマクロはテキストマクロ(textual macros)であり、Lispのマクロは構文マクロで(syntactic macros)ある。テキストマクロはテキストを置換し、構文マクロはマクロプロセッサが構文を解釈し別の式に置き換える。

LispやSchemeのマクロは高度な機能を持っているが、ふつうの人が関数呼び出しに比べて難しいと感じているのが問題だ。

マクロを組み立てるのは難しく、組み立てられたマクロを扱うのは単に慣れの問題で易しいが、そのマクロが正しく動くのかが判断しづらいため、マクロの利用は慎重的にならなければいけない。

Lispマクロの多くは構文をきれいにみせるために利用されるが、別の有用な利用法としてParse Tree Manipulationがある。ただし、Parse Tree Manipulationはマクロと直接関係があるわけではない。C# 3.0にはLINQを表現するためにクロージャの解析木を返す機能がある。これによりC#のクロージャとしてデータ構造上にクエリを表現できる。そして解析木を操作してSQLや他のクエリ言語に変換する。

Parse Tree Manipulationは強力だが少し複雑であり、どれだけ有用であるかを判断するのは困難である。めったに必要になることはないが、必要性が生じた場合は強力に威力を発揮する。広まるのはもう少し先のことになるだろう。

ファウラーへのフィードバック

担当者のつぶやき

  • この文章をPaul Grahamさんが読んだらどんな反応示すだろうか。
  • 結局のところ「言語側が用意してくれる」か「自分で好きなようにいじれる」か、なので好き好きかと。
  • でもこれだけネットなどのインフラやオープンソースコミュニティがあれば、マクロがある程度認知されれば、組み立て時に起こる問題の多くは解消されると思う。(楽観的すぎ?)
    • でもLispはマクロ以外にも他の障壁が多すぎる(遅延評価とか前置記法とか)

みんなの突っ込み