Js_of_ocaml -> calling the translated javascript

I’m unsure how to reference or call the generated javascript. It’s basically gibberish.

Say my ocaml is:

let rec sort = function
   | [] -> []
   | x :: l -> insert x (sort l)
and insert elem = function
   | [] -> [elem]
   | x :: l -> if elem < x then elem :: x :: l
               else x :: insert elem l;;

how would I call the translated javascript function?:

// something like this
// function sort(arr) {}
sort([3,1,2])

Js_of_ocaml is not really designed to be callable from JavaScript. Its output is a low-level ‘assembly-like’ version of JavaScript. This output is meant to be the final application that runs in the browser, not a library that’s called by other JavaScript consumers.

The same way you would in a standard OCaml program:

let () =
  ignore (sort [3,1,2])

Now, for a less toy example, it would depend on what the target is. For example, if the code is meant to be embedded in a webpage, the let () = ... code would perhaps take care of registering a callback on an onclick event of a button. Again, because everything is performed on the OCaml side, whether the resulting Javascript is gibberish does not matter.

so, say I was expecting to have some javascript function:

function sort(arr) {}

There’s no way to call the translated ocaml?

From JavaScript? No, not that I know of.

But from another OCaml source file in the same project? That’s trivial, just call it like a normal cross-module call.

You can definitely call Js_of_OCaml code from JavaScript. You just need to wrap it in an exported JS module.
See Export OCaml code to JavaScript.

I haven’t checked, but you will probably have to add conversions from JS arrays to OCaml lists in your OCaml code.

As other have mentioned that is perfectly possible.

But if the function you export is acting on OCaml values you will have to write a stub to convert from the JavaScript types you’d find natural to provide to the OCaml values your OCaml function expects.

In addition to @mnxn’s reference this is also lightly touched on in Brr's FFI cookbook here.

My mistake. Totally forgot about the export feature.

Thanks so much for your help.

I’m hitting a few potholes along the way. I’m unable to run the example at http://ocsigen.org/js_of_ocaml/dev/manual/rev-bindings:

$ cat math.ml
let _ =
  Js.export_all
    (object%js
      method add x y = x +. y
      method abs x = abs_float x
      val zero = 0.
     end)
$ ocamlfind ocamlc -verbose \
  -package js_of_ocaml -package js_of_ocaml-ppx \
  -linkpkg math.ml -o math.byte
Effective set of compiler predicates: pkg_bytes,pkg_uchar,pkg_js_of_ocaml,pkg_js_of_ocaml-ppx,autolink,byte
+ ocamlc.opt -verbose -o math.byte -I /home/g/.opam/default/lib/bytes -I /home/g/.opam/default/lib/uchar -I /home/g/.opam/default/lib/js_of_ocaml -I /home/g/.opam/default/lib/js_of_ocaml-ppx -ppx "/home/g/.opam/default/lib/js_of_ocaml-ppx/./ppx.exe --as-ppx" /home/g/.opam/default/lib/js_of_ocaml/js_of_ocaml.cma math.ml
+ /home/g/.opam/default/lib/js_of_ocaml-ppx/./ppx.exe --as-ppx '/tmp/camlppx16679a' '/tmp/camlppx8a9bc9'
File "math.ml", line 2, characters 2-15:
2 |   Js.export_all
      ^^^^^^^^^^^^^
Error: Unbound module Js
ocamlc.opt returned with exit code 2
$ ocaml -version
The OCaml toplevel, version 4.11.1
$ opam --version
2.0.8
$ ocamlc -version
4.11.1
$ uname -a
Linux manjaro 5.9.16-1-MANJARO #1 SMP PREEMPT Mon Dec 21 22:00:46 UTC 2020 x86_64 GNU/Linux

I changed math.ml in the following way to resolve this:

(*math.ml*)
-
+ open Js_of_ocaml

let _ =
  Js.export_all
    (object%js
      method add x y = x +. y
      method abs x = abs_float x
      val zero = 0.
     end)
// index.js
var math = require('./math.js');
console.log(math.add(2,3))

It now compiles:

$ node index.js
5

I have tried to do something similar some time ago for timere, in case you want a slightly more complex example

(I guess the main takeaway would be if you want to expose a Seq.t, it’s easier to make it into a generator function, and store the Seq.t in a ref, see method resolve)