はじめに
概要
BER MetaOCaml は OCaml でマルチステージ・プログラミングをするための OCaml 4.02.1 へのパッチである.
Installation
opam を使っていればインストールはとても簡単である.
opam update
opam switch 4.02.1+BER
eval `opam config env`
REPL
opam でインストールした MetaOCaml の REPL は次のようにして起動する.
metaocaml
特徴
最大の特徴はなんと言っても quote, unquote, eval であろう.例.
# let a = .<1 + 2>.;;
val a : int code = .<1 + 2>.
# let b = .<.~a * .~a>.;;
val b : int code = .<(1 + 2) * (1 + 2)>.
# open Runcode;;
# let c = !. b;;
val c : int = 9
.<x>.
で quote, .~x
で unquote, !.
で eval ができる.
なお, !.
は open Runcode
しないと使えない.
グローバルで open するのが気持ち悪いという人は多いと思うが, OCaml なので let open がある.
let c = let open Runcode in !. b;;
完全にレキシカル
.<x>.
は Lisp の `x
に似ているが,大きく異なる特徴がある.
それはシンボルのスコープである.
たとえば,次のようなコードはエラーになる.
# let c = .<x>.;;
Error: Unbound value x
要するに,シンボルは完全にレキシカルに扱われる.
変数は,定義した場所から見えるものだけが参照できる.
このことは,次のようなコードを実行してみれば確かめることができる.
# open Runcode;;
# let x = 1;;
val x : int = 1
# let a = .<x>.;;
val a : int code = .<1>.
# let x = 2 in !. a;;
Warning 26: unused variable x.
- : int = 1
これは,たとえば, let や aif のような,新しく変数を導入するマクロはつくれないことを意味する.例.
# let aif x y z = .<match .~x with Some it -> .~y | None -> .~z>.;;
val aif : 'a option code -> 'b code -> 'b code -> 'b code = <fun>
# let it = 1 in aif .<Some 2>. .<it>. .<3>.;;
- : int code = .<match Some 2 with | Some it_2 -> 1 | None -> 3>.
アナフォリック・マクロの禁止は,ポピュラーな機能である.
たとえば, Scheme の衛生的マクロ や Clojure のマクロも,マクロで新しい変数を導入することは基本的に禁止している.
扱えるのは式のみ
また, quote できるのは式のみという制限もある.
たとえば,次のようなコードは quote できない.
# let c = .<let hoge = 1>.;;
Error: Syntax error
これは,たとえば, Lens の makeLenses のように名前のついた関数の生成などはできないことを意味する.
型安全
型の合わないコードはつくれない.たとえば,
# let c = .<"a" - "b">.;;
Error: This expression has type string but an expression was expected of type
int
アナフォリック・マクロがつくれないなどの制限も多いものの,基本的に型安全である.
参考文献
- BER MetaOCaml 2015年2月24日アクセス.