generated at
KokaのEffect Handler





ref
koka(js)
fun raise-const() : int with ctl raise(msg) 42 // ① 8 + safe-divide(1,0) // ②
①で、 raise というeffectに対するhandlerを書いている
内容は、 raise() が呼ばれたら常に 42 を返す、というもの
②で、実際に関数を書いている
イメージ的にはJSの try/catch を逆の順序で書いてる
safe-divide が以下のような関数である場合
koka(js)
fun safe-divide( x : int, y : int ) : raise int if y==0 then raise("div-by-zero") else x / y
上記の raise-const を実行すると、
②が実行され、 1 ÷ 0 でraiseが呼ばれる
safe-divide の中で raise() が呼ばれる
①のhandler内にジャンプし、 42 を返す
これが raise-const の最終結果になる


resumeできる ref
koka(js)
fun raise-const() with ctl raise(msg) resume(42) // ③ resumeして42を返す 8 + safe-divide(1,0) // ④
Kokaのresumeを使うことで処理を再開できる
上記の raise-const を実行すると、
④が実行され、 1 ÷ 0 でraiseが呼ばれる
safe-divide の中で raise() が呼ばれる
③のhandler内にジャンプする
③は 42 を渡して、 safe-divide の処理を再開する
結果、 safe-divide の返り値は 42 になり、④で 8+42 が計算され 50 を返す
これが raise-const の最終結果になる


syntax suger
以下は同じ
koka(js)
fun raise-const() : int with handler ctl raise(msg) 42 8 + safe-divide(1,0)
koka(js)
fun raise-const() : int with ctl raise(msg) 42 8 + safe-divide(1,0)




文も書ける
koka(js)
fun ask-once() : int var count := 0 with ctl ask() count := count + 1 if count <= 1 then resume(42) else 0 add-twice()
条件分岐し、resumeするかどうかを決めてる






handleすることで、その関数からeffectが消えるのもポイント





fn を使うと最適化しやすくなるらしい
ただの糖衣構文ではない
evidence passingとかevidence vectorとかいう単語が出てくる
e.g. st, io, console



masking effects
普通にやると
koka(js)
effect fun emit( msg : string ) : () fun mask-emit() with fun emit(msg) println("outer:" ++ msg) with fun emit(msg) println("inner:" ++ msg) emit("hi") emit("there")
result
inner:hi inner:there
当然、内側のhandlerにのみ捕捉される
maskする
koka(js)
fun mask-emit() with fun emit(msg) println("outer:" ++ msg) with fun emit(msg) println("inner:" ++ msg) emit("hi") mask<emit> emit("there")
最も近いhandlerをmaskすることで、外側のhandlerに捕捉させる
;result
inner:hi outer:there