TL;DR

計算を「今」行う段階と「後で」行う段階に分け、後の段階で動くコードを生成するプログラムを型安全に書く技法。ステージングとも呼ぶ。Lisp の quasiquote / unquote によるマクロを、型付きにしたものに当たる。

なぜ必要か

MetaOCaml のページによると、ステージングは汎用的なコードから抽象化のオーバーヘッドを取り除くのに使われる。生成時に決められることを先に決めておけば、生成されたコードからはその判断が消える。

仕組み

MetaOCaml では、ブラケット .< e >. で式を囲むと、その式は「後で」計算されるコードになり、'a code 型の値として扱われる。ブラケットの中のエスケープ .~e は、e を「今」計算し、その結果を後で使うコードに埋め込む。Runcode.run は、生成したコードをコンパイルして関数として使えるようにする。MetaOCaml のページは「型の付いた MetaOCaml のプログラムは、型の付いたプログラムしか生成しない」としている。

mimium の発表によると、ステージ 0 がコンパイル時(マクロ)、ステージ 1 が実行時になる。型チェックと型推論は展開の前に終わる。

例

MetaOCaml のページは、x の n 乗を例に挙げている。n を先に与えてコードを生成すると、生成された関数には再帰も偶奇の判定も残らない。

多段階計算によるコンパイル時テンソル形状検査では、テンソルの形状の assertion をステージ 0 に、テンソルの計算をステージ 1 に置く。コードが生成できれば、実行しても形状の不整合が起きないことが保証される。mimium は、多段階計算でテキストのパーサをコンパイル時に動かし、言語の上に別の DSL を埋め込んでいる。

注意点

MetaOCaml のページによると、ステージングは非常に明示的で、どの計算をどの段階で行うかをプログラマが書く必要がある。

関連

出典