ただし、正確には、継続は関数とは違う。 継続1のあとに継続2を実行しようとしても、 関数合成のようにはならず、継続1 を実行しおわったら(継続2を 実行せずに)終わってしまう。 従って、正確には、継続は、(fun v -> exit(1+2*v)) といった関数 のようなものである。ここで exit は「終わる」という意味の C言語の exit() 関数と同じつもりである(OCaml にはないので、 こんな式を書いてはいけない。仮想的なものである。)
このような「継続」を使って、インタープリタをここに載せてしまうので、 見てみてほしい。このプログラムがどう動いているかを自力で理解すると、 関数プログラミングの神髄がわかるであろう。
(**************************************************************************) (* eval7 : exp -> env -> (value -> 'a) -> 'a *) (* 継続渡し形式のインタープリタは value を返すのではなく、(value->'a) と いう関数をもらって、'a型の要素を返す。ここで'aは、どんな型でもよい *) let rec eval7 e env cont = match e with | Var(x) -> cont (lookup x env) | IntLit(n) -> cont (IntVal n) | BoolLit(b) -> cont (BoolVal b) | Plus(e1,e2) -> binop (+) e1 e2 env cont | Times(e1,e2) -> binop ( * ) e1 e2 env cont | Eq(e1,e2) -> eval7 e1 env (fun v1 -> eval7 e2 env (fun v2 -> cont (BoolVal (eq_val v1 v2)))) | If(e1,e2,e3) -> eval7 e1 env (function | BoolVal(true) -> eval7 e2 env cont | BoolVal(false) -> eval7 e3 env cont | _ -> raise Wrong_Value) | Let(x,e1,e2) -> eval7 e1 env (fun v1 -> let env1 = ext env x v1 in eval7 e2 env1 cont) | LetRec(f,x,e1,e2) -> let env1 = ext env f (RecFunVal (f, x, e1, env)) in eval7 e2 env1 cont | Fun(x,e1) -> cont (FunVal(x, e1, env)) | App(e1,e2) -> eval7 e1 env (fun funpart -> else false | (ListVal(_),ListVal(_)) -> false ... (* テスト *) let ee = emptyenv () let initial_continuation = fun a -> a let eval7top e = eval7 e ee initinal_continuation let _ = eval7top (IntLit 1) let _ = eval7top (IntLit (-1)) let _ = eval7top (Plus (IntLit 1, Plus (IntLit 2, IntLit (-1)))) let _ = eval7top (Times (IntLit 1, Plus (IntLit 2, IntLit (-1)))) ...
亀山幸義