I was playing around with some toy code and I got some (seemingly) interesting differences in JS output. The question I have is why the examples which seem to have pretty similar ReScript code all get pretty different JS output. (Examples follow.)
Simple way
If you have code like this:
type document
@val external document: document = ""
@send external getElementById: (document, string) => Dom.element = "getElementById"
let apple = getElementById(document, "apple")
Then you get nice compact JS output:
var apple = document.getElementById("apple");
Putting the code in a simple module like this:
module Docu = {
type t
@val external document: t = ""
@send external getElementById: (t, string) => Dom.element = "getElementById"
}
also gives you the same JS.
Module split into .res and .resi
If I split the module into a .res
file:
type t
@val external document: t = ""
@send external getElementById: (t, string) => Dom.element = "getElementById"
And a .resi
file:
type t
let document: t
let getElementById: (t, string) => Dom.element
Then my JS looks like this:
'use strict';
var $$document = document;
function getElementById(prim, prim$1) {
return prim.getElementById(prim$1);
}
exports.$$document = $$document;
exports.getElementById = getElementById;
And when I actually use that code from another module (eg different file…whatever)
let apple = DocuThing.getElementById(DocuThing.document, "apple")
Then I get this:
var DocuThing = require("./DocuThing.bs.js");
var apple = DocuThing.getElementById(DocuThing.$$document, "apple");
Now, the ReScript code looks pretty much the same as the simple module except that you have a signature to go with it and it changes the JS output. Let’s check one more example.
Weirder Example
Here are a couple of different module definitions that give yet different JS output.
module Docu2: {
type t
let document: t
let getElementById: (t, string) => Dom.element
} = {
type t
@val external document: t = ""
@send external getElementById: (t, string) => Dom.element = "getElementById"
}
let good = Docu2.getElementById(Docu2.document, "good")
module type Docu3 = {
type t
let document: t
let getElementById: (t, string) => Dom.element
}
module Docu3: Docu3 = {
type t
@val external document: t = ""
@send external getElementById: (t, string) => Dom.element = "getElementById"
}
let sweet = Docu3.getElementById(Docu3.document, "sweet")
And the generated output looks something like this:
function Docu2_getElementById(prim, prim$1) {
return prim.getElementById(prim$1);
}
var Docu2 = {
$$document: document,
getElementById: Docu2_getElementById
};
var good = Curry._2(Docu2_getElementById, document, "good");
function Docu3_getElementById(prim, prim$1) {
return prim.getElementById(prim$1);
}
var Docu3 = {
$$document: document,
getElementById: Docu3_getElementById
};
var sweet = Curry._2(Docu3_getElementById, document, "sweet");
That gives another, different JS output…this time with the explicit JS currying methods.
Wrap up
Okay, so that was long winded, but I’m pretty curious about what leads to the different JS output. If anyone could shed some light on the matter that would be great!!