Phrase terminator ;; について

なんだか OCaml の syntax についていちゃもんをつけている人がちらほらと。
ほとんどは「俺様好き好き言語と違うからイヤ」という言いがかりレベルに近いので、ほっときます。ただし、次の 2ch ML板のコメントは理解できます:

SMLから入ったからOCamlシンタックスには戸惑ったな。
;;だけは未だに抵抗を感じる。ファイルに書くときはどうせ最後にしか書かないから
ほぼ関係ないが、toplevelを使うときにはやっぱり面倒くさい。

一体どんな経緯で;;になったの?

OCaml は CAML, Caml-Light, Caml Special Light, Objective Caml と進化してきました*1が、CAMLの時点から interactive toplevel の式(phrase)終了の記号は ;; でした。(CAML はまだヒッソリと INRIA の ftp サイトに残っています: ftp://ftp.inria.fr/INRIA/cristal/caml/V2-6.1/。マニュアルを見れば ;; が使われているのが判ります。)

さて、ではなぜ CAML は ;; を toplevel phrase terminator に使っているのか。ちょっと古いことなので、自分で調べるよりは当事者に聞いた方がいいだろうと、私の博論を指導してくれた Pierre Weis に聞いてみました。Personal communication なので、いろんな事が書いてあるからそのまま引用できませんが、要点だけ日本語で:

複数行に渡る式を書きたいから、改行で phrase が終わり、はダメ

これは当然ですね。

end はイヤだった

この end とは、let pat = e1 in e2 end みたいな書き方の事です。今では Ruby なんかがこの文法ですね。これだと、toplevel では let で始まれば、end が来るのを待てばよい。Sequence でも e1; e2 の代わりに、 ( e1; e2 ) とか、 begin e1; e2 end と書けば、phrase の終了位置ははっきりしますから、 terminator は必要ありません。ただ、こういう文法にしちゃうと、 toplevel 以外で面倒臭くなります。例えば、ML では local let が頻出します。いちいち end を書いていると大変ですね:

let f x =
  let y = ... in
  let z = ... in
  let w = ... in
    ...
  end
  end
  end
end

どんどん let と end の距離が離れていって、どれが対応しているのかわかり難くなります。
end を書かないことにすれば、toplevel phrase の終了を示す、何かの記号が必要になりますね。

, . : ; は既に使われていた

各記号の用法は述べるまでもないでしょう。なので、別の記号が欲くなります。SML の様に、; でもよかったんですけど、そうすると、( e1; e2 ); とか、(これは e1; e2; と逐次実行でいいけど)、(let pat = e1 in e2; e3); や、 let pat = e1 in begin e2; e3 end; などと書かなくてはいけません。上記の end はイヤの思想に反します。

っつーか、そもそも ;; は Robin Milner の ML で terminator として使われていた

だから、採用しない理由がないよね。だそうです。
ML や LCF の論文で、私の見れる範囲の物を探しましたが、証拠は見付かりませんでした。LCF のマニュアルとか見れば判ると思います。誰か大学図書館に近くてヒマな人(がいれば)調べていただければ、、、

まとめ

便利だし、元祖が採用していたから、でした。もちろん、SML が ;; を採用しなかったように、元言語の真似をする必要は必ずしも無いわけですけど。ML が 74 年だそうですから、えーっと、引き算してよ。伝統あるんですよ。(俺自身よりは伝統ないけど。)
と言うわけで、安心して ;; を使ってください。必須なのは toplevel だけですから。プログラムファイル中でも ;; は使えるし、時々エラーを発見するのに便利な事もありますけど、必須ではありません。(むかしの OCaml はそもそも ;; をプログラム中で使うとエラーだったような記憶があります。)

*1:Guy Cousineau: A brief history of Caml (as I remember it). これを読めばなぜ彼らが SML と並行して自分自身の関数型言語実装を行ったかが書いてあります。標準化もいいけど、まず自分達のアイデアをどんどん試せるテストベッドが欲しかったようです。確かにCAMLにはその子孫には受け継がれなかった奇怪な機能が幾つもあります。