generated at
Kokaのoperation keywords

↑正式な総称が不明なので適当にタイトルを付けているmrsekut
KokaのEffect Handlerを書くときに登場する以下のようなキーワードについて
ctl
val
return
fun


ctl
最も愚直にhandlerの内容を書く方法
with ctl op(<args>){ <body> } という構文
koka(js)
fun raise-const() : int with ctl raise(msg) 42 ...
raise というeffectに対するhandlerを定義している


fun
以下2つは同じ意味
koka(js)
with fun op(<args>){ <body> }
koka(js)
with ctl op(<args>){ val f = fn(){ <body> }; resume( f() ) }
ただし、内部的にはただの糖衣構文ではなく、前者の方が最適化しやすいらしい
Kokaのresumeとして実行する関数を簡潔に書ける
fun と書いた時点で、resumeすることが含意されている
そのため、 fun の方にはわざわざ resume というキーワードが登場しない
koka(js)
fun ask-const2() : int with fun ask() 21 add-twice()
こんなふうにも読めそうmrsekut
handlerではない実際の処理側で、 ask を使っている箇所を、全てここで定義したものに置き換える
つまり、injectionしてる





val
以下2つは同じ意味
koka(js)
with val v = <expr>
koka(js)
val x = <expr> with ctl v(){ resume(x) }
value operationを簡潔に書く記法
koka(js)
// 値としてeffectを用意 effect val width : int // `width`を内部で使っている関数。`width`は引数で受け取っているわけではない fun pretty-internal( line : string ) : width string line.truncate(width) // 上記の関数を呼び出すhandler。width=40と設定して実行している fun pretty-thin(d : doc) : string with val width = 40 pretty(d)
値をeffectで表現することで、外側から値のinjectionができる
安全なglobal変数とも見れる
引数でバケツリレーする必要もなく、globalなmutable変数とも違う
型で明示されるので設定し忘れがない
pretty-thin 以上の呼び出し元からは width を変更することはできない
スコープが限られている
そのglobal変数は、どこからでも変更可能、にはなってなくて安心安全



return
特定のhandlerを通過せずに、通常終了したときの最終返り値を変換するだけ
raiseをmaybeに変換するhandler
koka(js)
fun raise-maybe( action : () -> <raise|e> a ) : e maybe<a> with handler return(x) Just(x) // normal return: wrap in Just ctl raise(msg) Nothing // exception: return Nothing directly action() fun div42() (raise-maybe{ safe-divide(1,0) }).default(42)



raw ctl