4. Static binding と dynamic binding
static な変数は、プログラムの lexical な構造から値が
決まる
let x = 0 in
let f () = x in
let x = 1 in
f () ;; → 0
dynamic な変数は、それを含む関数などが呼び出され
たときの環境から値が決まる
dlet x = 0 in
let f () = x in
dlet x = 1 in
f () ;; → 1
7. OCaml での実装
τ dynvar
τ 型のパラメータに対する abstract type constructor
dnew : unit -> ’a dynvar
Σ から τ 型のパラメータを選んでくる
dref : ’a dynvar -> ’a
パラメータの現在の値にアクセスする
dlet : ’a dynvar -> ’a -> (unit -> ’b) -> ’b
dlet p = V in M を表す
8. プログラムの例
let p = dnew () in
dlet p 0 (fun () ->
let f = fun () -> dref p in
let x = f () in
let y = dlet p 1 (fun () -> f ()) in
let z = f () in (x, y, z))
→ (0, 1, 0)
9. プログラムの例
let p = dnew () in
dlet p 0 (fun () ->
let f = fun () -> dref p in
let x = f () in
let y = dlet p 1 (fun () -> f ()) in
let z = f () in (x, y, z))
12. OCaml での実装
τ prompt
τ 型のプロンプトに対する abstract type constructor
new prompt : unit -> ’a prompt
新しいプロンプトを作る
push prompt : ’a prompt -> (unit -> ’a) -> ’a
reset p in M を表す
shift : ’a prompt -> ((’b -> ’a) -> ’a) -> ’b
shift p as f in M を表す
13. プログラムの例
let p = new prompt () in
push prompt p (fun () ->
1 + shift p (fun f -> f (f 2)))
f = push prompt p (fun () -> 1 + [ . ])
14. プログラムの例
let p = new prompt () in
push prompt p (fun () ->
1 + shift p (fun f -> f (f 2)))
15. プログラムの例
let p = new prompt () in
push prompt p (fun () ->
1 + shift p (fun f -> f (f 2)))
16. 従来の実装の問題
dlet p = 1 in reset in p
→ 1?
dlet p = 1 in reset in dlet p = 2 in shift as f in p
→ 1?
(λf. dlet p = 2 in dlet r = 20 in f(0))
(dlet p = 1 in reset in dlet r = 10 in
(λx. p + r)(shift p as f in f))
→ 12?
18. 問題点
dlet p = V in M の型は p の型と無関係
reset p in M と p はともに M と同じ型を持つ
19. 問題点
let p = dnew () in
dlet p 0 (fun () ->
let f = fun () -> dref p in
let x = f () in
let y = dlet p 1 (fun () -> f ()) in
let z = f () in (x, y, z))
→ (0, 1, 0)
dlet に対する push prompt :
int -> int
dlet に対する push prompt :
int -> (int * int * int)
20. DB から DC への翻訳: Ver. 2
dlet p = V in ... が値 z になったら、delimited
context を abort し、プロンプト q までジャンプする
ignore = λx. ? : τ1 → τ2 は、reset p in ... が値を
返さないことを保障
OCaml では
let ignore x = failwith "cannot happen".
21. OCaml での実装
type ’a dynvar = (’a -> ’a) prompt
let dnew () = new prompt ()
let dref p = shift p (fun x -> fun v -> x v v)
let dlet p v body =
let q = new prompt () in
push prompt q (fun () ->
ignore ((push prompt p (fun () ->
(fun z -> shift q (fun -> z))
(body ())))
v))