pa_monad を通して camlp4 のコマンドラインを思い出す

pa_monadOCamlモナドを使いやすくするための構文拡張だ. ついこの前 id:camlspotter さんが pa_monad の拡張を書いてくださった.ありがたや. 早速使ってみようと思い,コンパイルした.hg clone https://bitbucket.org/camlspotter/pa_monad_custom でダウンロードしたあとは make一発です.

ただ,ちょっと ocamlc から試そうと思ったら,俺 camlp4コマンドラインオプションを全然覚えてないよ,ということに気づいた. いつも忘れるので書いておく.

ocamlc -pp 'camlp4of pa_monad.cmo' a.ml

ocamlc/ocamloptのオプション -pp に続けてプリプロセッサコマンドラインを書く.

しかしそもそも camlp4of とはなんだろう? camlp4 には camlp4o, camlp4of, …などの種類があり,素人には分かりにくい.

結論からいえば,普通は camlp4of を使っていれば良い. ここで o は Orignal syntax の O で, f は 全ての(full)構文を使うということだ. 万が一, camlp4拡張を自分で書くときには camlp4oof, camlp4orf を使えばいい. 細かい違いについては後で書く.

ちゃんと調べたら簡単だった…

ocamlfind から camlp4 を利用 : ocamljs の場合

ただ ocamljsJavaScript 構文拡張など,多数の依存ライブラリを含む場合,

camlp4of -I /opt/local/lib/ocaml/site-lib/ulex -I /opt/local/lib/ocaml/site-lib/jslib ulexing.cma jslib.cma syntax_inline.cmo

などと,-I で参照するライブラリを指定して,依存ライブラリを 全て渡してやらないといけない. こうなると面倒なのでocamlfindを使う.(omakeはどう使うんだろう…)

幸い ocamljs は ocamlfindjs というカスタマイズされたocamlfindがついてくるので, JavaScript の構文拡張を使う場合は

ocamlfindjs ocamljs -syntax camlp4of -package jslib.inline, -c a.ml

とするだけで良い. ここで jslib.inline は jslib パッケージの一部で, ocamlfind の site-lib 下の jslib/META に詳しい内容が書いてある.
ocamlfindjs でなく ocamlfind の場合も

ocamlfind ocamlc -syntax camlp4of -package パッケージ名 -c a.ml

などとすればいい.

pa_monad の ocamlfind化

pa_monad を ocamlfind 化してみよう. まず META という名前のファイルを次の内容で準備する:

name = "pa_monad"
archive(syntax,preprocessor) = "pa_monad.cmo"

この METAを pa_monad.cmo と同じ位置に置き,

sudo ocamlfind install pa_monad META pa_monad.cmo

とすれば, /opt/local/lib/ocaml/site-lib/pa_monad 以下にふたつのファイルがコピーされる.あとは,

ocamlfindjs ocamljs -syntax camlp4of -package pa_monad,jslib.inline -c a.ml

などとすればいい.
ここで jslib.inline と pa_monad の両方を指定している.複数の構文拡張を共存させられるのが camlp4 のすごいところだ.

camlp4, camlp4o, camlp4of, camlp4oof, …

camlp4o* …どう違うのか.
このあたりUndocumented気味なので正直自分も正確に把握していないのだが, 公式Wiki? を読んで,次のようになっているのではないかと思った.

camlp4(o(f|of|rf)?)?
  • camlp4 単体だと何もparseしない. camlp4 -parser o … などと他のオプションで細かくparse/printするときのみ使う.
  • camlp4o 拡張構文なし
  • camlp4of 拡張構文(ストリームやリスト内包表記など)あり.
  • camlp4oof 拡張構文あり. さらにメタ構文 (<:str_item< ... >> とか) が書けるようになる. <:???< ... >> の中身は original syntax.
  • camlp4orf 拡張構文あり. さらにメタ構文が書けるようになる. <:???< ... >> の中身は revised syntax.

正直,ただの camlp4of でリスト内包表記ができるようになることを今まで知らなかった… [i * 2 | i <- [1;2;3]] みたいに書けます.

camlp4rf?
  • camlp4r revised syntax.
  • camlp4rf revised syntax と 拡張構文.

camlp4 -parser p -parser op -printer a とか, -filter とか,まだまだ知らないオプションは多い…