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]; OCaml Revised fun x -> x fun x -> x fun {foo=(y, _)} -> y fun {foo=(y, _)} -> y 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) -
具体的な型ではコンストラクタの周りに [ ] が必要。
OCaml Revised 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 節は必須。
or や & は無い。|| と && のみを使う。OCaml Revised if a then b if a then b else () OCaml Revised a or b & c a || b && c a || b && c a || 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 []
なんかテーブルを使ったのは間違いだったような…。
- コンストラクタの無い型を作れる。