Some overloading is possible using a syntactic trick: names _foo, foo_abcd and foo are all mapped to a same Javascript field name foo: when accessing a field of an object, the name given in the OCaml code is transformed by removing a leading underscore and then removing all characters starting from the last underscore; this yields the corresponding Javascript name. For instance, these three types correspond to the same Javascript method drawImage:
I also was quite confused about the js_of_ocaml js interface. Did not manage to achieve what i wanted and in the end I gave up and tried Brr instead. It was a much more pleasant experience. No ppx magic and the documentation is quite good.
In my case I was trying to interact with the Cloudflare worker runtime environment. So no prebuilt library was provided, I had to use the Brr FFI. Thanks to the documentation with all the examples, it was mostly a breeze.
I never got the hang of Brr; anytime I was trying to convert a JS snippet to Brr, the provided API never quite matched up with the MDN docs; I never found a good way to determine if (1) the API was not in Brr and I should bind it myself or (2) the API was in Brr, but I was not finding it.
A few JavaScript APIs were remixed because they were too broken to work with, mostly the old DOM stuff.
However before people start making wrong inferences from your comments Iâd like to point out that most of the time in Brr:
There is a one to one correspondance between Brrâs representation and browser APIs according to this naming convention. Sometimes a few API prefixes are factored out in a module e.g. (MIDIInput â Midi.Input).
This representation is thoroughly documented by linking into MDN. Each type representing a JavaScript object documents which object it represents with a link on its definition on MDN. Each function acting on a type has a direct link on the corresponding functionality it binds to on MDN.
There is an index of which browsers APIs are bound.
But of course to benefit of all that you need to read the docs.
Exhaustiveness is an explicit non-goal of the project. As far as browsers API go thereâs a ton of outdated things you should not use. Itâs one of the goal of brr to save your time by not binding to the useless stuff.
If I understand your post correctly, you are talking about Brr doc linking to MDN doc.
I am interested in the inverse problem: given a MDN class/function name, how easy is it to guess the corresponding Brr function to use ? This is the problem I run into all the time when manually porting from JS to OCaml.
I would argue that Brr is not optimized for this at all. There seems to be many naming quirks that makes sense for Brr internally but makes it hard to go from (JS Class, JS method) to corresponding Brr function. Examples of this include:
other small inconsistencies I canât recall right now
Individually these are small quirks; from the perspective of âhereâs a blob of JS code, rewrite it in OCamlâ, these mental âpebblesâ largely prevented me from ever getting into âflow stateâ when translating JS to Brr.
Something else: in my opinion (and I may be entirely wrong here), I think the Jsoo âclassâ based technique works better than a âfunctionalâ approach for the following reason.
Suppose we have:
1. a JS line that looks like:
obj.foo(arg1, arg2, arg2);
2. we know that the type of obj is Orange
that we want to translate to OCaml.
In the case of Brr, Iâm not sure how to grep for this function âfooâ â I need to guess which module corresponds to type Orange ; then a function that is named âfooâ-ish ; but things may not be arranged this way as matching MDN layout is not the highest objective
In the case of Jsoo, I grep for âclass type [guess based on Orange]â, then after I find it, I get something of the form: [1]
class type orange = object
method ... = Js.readonly_prop / Js.method
end
and all the methods are there in one place, and I find the one closest to âfooâ.
From the perspective of not reading the docs, the layout of the code and the use of classes makes it much easier to guess/find the right function name to use.
[1] In the class case, I donât even have to guess, I can just do:
let obj: () = ...
and the compiler error will tell me approximately the correct class type of obj
The already mentioned index provides a map to that. MDN docs are also quite arbitrary regarding this.
In general new large well delineated APIs get their own namespacing module. For the rest I wanted to avoid to have to open dozens of modules. The state of Jsoo separatate compilation when this was done also likely got taken into account.
Iâm not claiming this is the best way of distributing, but then no one proposed something better.
The URL JavaScript module is totally broken. Uri is named that way because it works differently from URL, thatâs mentioned in the docs of course.
Thatâs likely a mishap, I bound thousands of entry points during different, long and boring periods. I donât guarantee there isnât a few occurences where I got distracted from the discipline or that the whole thing is totally consistent. This could have been reported.
Since it seems you are mainly interested in translating JavaScript code as OCaml then you are right thatâs exactly what jsooâs approach give you: the ability to write typed and idiomatic JavaScript code in OCaml with unscrutable type error messages.
Personally Iâm interested in writing OCaml code, not JavaScript, and thatâs the reason why Brr had to be devised.
I think this might be a misunderstanding of Brr and JSOO. Jsoo, in general, encourages mixing JS values in your Ocaml code, sorting of two languages meeting as one. From my usage of Brr, it is an FFI, which means itâs meant to be used only on the boundary. So your program is almost entirely ârealâ Ocaml values, and at the edges, where it interacts with JS, you use Brr to translate. This is simlar to how FFI works in most other situations, for example consider when you call C functions from Ocaml.