これからのOCamlについての噂 #1: local module open

OCaml では、モジュール M で定義されている型や値にアクセスするには M.hoge という記法を使う。M 中の型や値を頻繁に使う場合、一々 M.fuga, M.Poge と書いていると面倒になってくる。こういう時に、 open M と唱えると、それ以降、 M. を付けなくても、 fuga, Poge で M 中の名前を参照できるようになる。

ただ、現在の OCaml では、一度 open してしまったモジュールは閉じることが出来ない。そのため、open を多用しすぎると名前空間がグチャグチャになっちゃう。例えば、

open M
open N
let _ = x

と書いたとき、x は M.x なのか、 N.x なのか?わかりづらい。(というか、この文面からだけでは全く判断できないね。) open は適切に使えばプログラムの可読性を向上させるんだけど、使いすぎると逆に下がってしまう。この「適切」がちょっとトリッキーなので、ある程度 open で苦労しないと程よい使いかたはマスターできないんじゃないかと思っている。

open したモジュールを close できれば、少しは見通しがよくなるのだが、close M なんてのは無粋だ。この、open と close を組み合わせて、ローカルにモジュールを open できる機能があれば、とても嬉しい。

実は、現在の OCaml にも、 OpenIn という CamlP4 拡張があって、これを使うと次のようにモジュールをローカルに open できる:

open M in e

こうすると式 e の中*だけ*で、モジュール M 中の定義が open できるわけ。便利。

ただ、OpenIn 拡張にも問題がある。上のプログラムは OpenIn を使うと(多分)次のような拡張無しの OCaml プログラムに変換される:

let module N = struct
  open M
  let v = e
end in 
N.v

これ自体、動作は全く正しいんだけど、モジュール用にブロックを一度作って、そこから値を一度アクセスするというコードになっている。なので、ランタイムにほんの少しだけれどペナルティがある。ほんの少しだけれど、再帰やループの中で open M in を使うと、それも無視できなくなってくる。open M in は名前空間の操作であって計算ではないので、これは全く嬉しくない。

そもそもこんな機能は言語自体に付け加えるべきなんで、CamlP4 で実現するのってのは手軽だけど、本質的には間違ってる。

作者の Alain Frisch は Caml チームの元メンバーなので、OCaml 自体にそんな拡張を付け加えるのは朝飯前*1なんだけど、その OCaml 拡張を正式なバージョンに取り込んでもらうのはいろいろと面倒だったみたい。OCaml へのパッチとして出してもよいのだけれど、使いたい人はコンパイラを改造しなきゃいけないし。CamlP4 の拡張として敢えて出したのは利便性を考えての事だろう。

さて、この open M in だが、次の OCaml にはちゃんと取り込まれて、上で書いたランタイム・オーバーヘッドも無くなる。ということを風の便りに聞いた。よいことだ。

*1:少なくとも、同じ機能を提供する CamlP4 拡張書くのより簡単にできるはずだ