js_of_ocaml
ハマったところ幾つかメモ。Js.Unsafeは名前の通りUnsafeだった。
Js.Unsafe.variable
Js.Unsafe.variableはごく普通にjs_of_ocamlが生成する関数内のスコープでが展開される。
何が起こるかというと、js_of_ocamlが生成する変数と名前の衝突が起こり、本当に見たかった変数が隠されてしまう。
let index_of array value from_index = Unsafe.meth_call (Unsafe.variable "$") "inArray" [|Unsafe.inject value; Unsafe.inject array; Unsafe.inject from_index|];;
で、$が隠されて意図した動作をしなかった。
厄介なことに -pretty の有無で変数名が変わるのでしばらく発覚していなかった。
let index_of array value from_index = Unsafe.meth_call (Unsafe.variable "jQuery") "inArray"
に変更して対処。
別名がない3文字程度までの外部の変数を参照する必要がある場合は、一端長い名前の別名をJavaScript側で定義するのが安全だと思う。
Js.Unsafe.fun_call
JavaScriptの関数呼び出しで
function js_foo(a) { return doA(a); }
let foo: a -> b = Unsafe.variable "js_foo" ignore (foo bar);;
としていた。
これがライブラリのバージョンアップで
function js_foo(a, b) { if (typeof a === "undefined") { return doA(a); } else { return doAB(a, b); } }
となっていた。これはJavaScriptでは合法。
だけどOCaml側では foo a; が js_foo への部分適用の状態になるので、b -> cが帰る。
さらに戻り値がメソッドチェーン用で使わないのでignoreしてたのも事態をややこしくしてた。
ここは面倒くさがらずに Unsafe.fun_call を使うようにする。
let foo a = Unsafe.fun_call (Unsafe.variable "foo") [| Unsafe.inject a |];;