Camlp4 の改訂構文

Camlp4 の改訂構文がややこしい。後で見直しやすいようにThe Revised syntax を適当に訳しておく。翻訳ってレベルじゃないけど。

  • in の無い let は value を使う。
    OCaml Revised
    let x = 23;; value x = 23;
    let x = 23 in x + 7;; let x = 23 in x + 7;
  • シグネチャでは val の代わりに value を使う。
    OCaml Revised
    val x : int;; value x : int;
  • ; で繋げてるところは do { ... } で囲う。最後に ; を置いてもいい。
    OCaml Revised
    e1; e2; e3; e4 do { e1; e2; e3; e4 }
  • for と while も同じ。
    OCaml Revised
    while e1 do while e1 do {
    e2; e3; e4 e2; e3; e4
    done }
  • タプルでは括弧が必須
    OCaml Revised
    1, "hello", World (1, "hello", World)
  • リストは常に [ ] で囲う。
    list            ::=     [ elem-list opt-cons ]
    elem-list       ::=     expression ; elem-list | expression
    opt-cons        ::=     :: expression | (*empty*)
    リストは [ ] の中に式を ; で区切っていれる。最後の要素にだけ :: が付いてもよい。
    OCaml Revised
    x::y [x::y]
    [x; y; z] [x; y; z]
    x::y::z::t [x::[y::[z::t]]]
    x::y::z::t [x; y; z :: t]
  • irrefutable pattern とは決して失敗しないパターンだが、
    type foo = Foo
    の Foo みたいなのは含まない。() は含む。*1
  • function は使わない。fun のみを使う。
  • fun, match, try 中のパターンマッチは [ ] で囲う。
    OCaml Revised
    match e with match e with
    p1 -> e1 [ p1 -> e1
    p2 -> e2;; p2 -> e2 ];
    fun x -> x;; fun [x -> x];
    パターンが一つしかなくて、しかもそれが irrefutable なら [ ] は必要無い。
    OCaml Revised
    fun x -> x fun x -> x
    fun {foo=(y, _)} -> y fun {foo=(y, _)} -> y
    カリー化したパターンは fun で使えるが、irrefutable なもののみ。
    OCaml Revised
    fun x (y, z) -> t fun x (y, z) -> t
    fun x y (C z) -> t fun x y -> fun [C z -> t]
  • fun や match でパターン無しのものを書くことができる。常に Match_failure 例外が起こる。try で同じことをすると try が無かったときと同じになる。
    fun []
    match e with []
    try e with []
  • let や value のパターンは irrefutable のもののみ。
    OCaml Revised
    let f (x::y) = ... let f = fun [ [x::y] -> ...
  • where が使用可能。ただし、束縛できるのは一つだけ。
    e where x = y
    はできるが
    e where x = y and z = t
    はできない。
  • <- の代わりに := を使う。
    OCaml Revised
    x.f <- y x.f := y
  • ref 型は val という名前のフィールドの[[]]みを持つレコードになっている。! 演算子は無い。
    OCaml Revised
    x := !x + y x.val := x.val + y
  • 型コンストラクタが Haskell っぽい。*2
    OCaml Revised
    int list list int
    ('a, bool) Hashtbl.t Hashtbl.t 'a bool
    type 'a foo = type foo 'a =
    'a list list;; list (list 'a);
  • 抽象型は未束縛な型変数を使う。*3
    OCaml Revised
    type 'a foo;; type foo 'a = 'b;
    type bar;; type bar = 'a;
  • タプル型では括弧が必須。
    OCaml Revised
    int * bool (int * bool)
  • 具体的な型ではコンストラクタの周りに [ ] が必要。
    OCamlRevised
    type t = A of i | B;;type t = [ A of i | B ];
  • コンストラクタの無い型を作れる。
    type foo = [];
  • 複数の引数を持つコンストラクタと、引数がタプル一つのコンストラクタの文法は別。 複数の引数を持つコンストラクタは型を and で区切って書く。その場合はカリー化される。
  • OCaml Revised
    type t = C of t1 * t2;; type t = [ C of t1 and t2 ];
    C (x, y);; C x y;
    タプル一つを持つコンストラクタはこれとは異なる。
    OCaml Revised
    type t = D of (t1 * t2);; type t = [ D of (t1 * t2) ];
    D (x, y);; D (x, y);
  • True と False は大文字で始まる。
  • レコード型で、 mutable は : の後に置かれる。
    OCaml Revised
    type t = {mutable x : t1};; type t = {x : mutable t1};
  • モジュールの適用はカリー化される。*4
    OCaml Revised
    type t = Set.Make(M).t;; type t = (Set.Make M).t;
  • オブジェクト関係にも改訂構文がある。次のコマンドを使えば、通常の構文から改訂構文への変換してくれるので試してみるといいだろう。*5
    camlp4o pr_r.cmo file.ml
  • else 節は必須。
    OCaml Revised
    if a then b if a then b else ()
  • or や & は無い。|| と && のみを使う。
    OCamlRevised
    a or b & ca || b && c
    a || b && ca || b && c
  • begin ... end は無い。括弧を使う。
  • 演算子を関数として使うときは \ を付ける。
    OCaml Revised
    (+) \+
    (mod) \mod
  • 二項演算子は自動的に定義されない。構文拡張で定義する。
  • It is possible to group together several declarations either in an interface or in an implementation by enclosing them between ``declare'' and ``end''. Example in an interface:
    declare
     type foo = [ Foo of int | Bar ];
     value f : foo -> int;
    end;
    This can be useful when extending the language structure or signature items with a construction generating several items. *6
  • ストリームとストリームパターンは [< ... >] の代わりに [: ... :] を使う。
  • ストリームの終端記号は クオート(')の代わりにバッククオート(`)を使う。
    OCaml Revised
    [< '1; '2; s; '3 >] [: `1; `2; s; `3 :]
  • fun や match と同様、パーサの分岐は [ ] で囲う。一つしかなければ必要ない。
    OCaml Revised
    parser parser
    [< 'Foo >] -> e [ [: `Foo :] -> e
    [< p = f >] -> f [: p = f :] -> f ]
    parser [< 'x >] -> x parser [ [: `x :] -> x ]
    parser [< 'x >] -> x parser [: `x :] -> x
  • 空のパーサやストリームを定義できる。これらは常に Stream.Failure 例外が起こる。
    parser []
    match e with parser []

なんかテーブルを使ったのは間違いだったような…。

*1:ちゃんとした定義は原文で

*2:これは意訳というか超訳

*3:なんじゃこりゃー

*4:というか括弧無しで書けるということ?

*5:説明しろよ!

*6:これよくわからん