It is common practice in JavaScript to have a function that takes in an options parameter, like so:
function foo({ bar1, bar2, bar3 }) {}
foo({ bar1: 5, bar2: 3 })
In Reason/OCaml, one would prefer to use labelled arguments for these functions:
let foo = (~bar1, ~bar2, ~bar) => {}
foo(~bar1=5, ~bar2=3, ())
Now, I know there is this way of creating Reason/Bucklescript bindings for functions like these:
type barObj;
[@bs.obj] external makeBarObj : (
~bar1: int=?,
~bar2: int=?,
~bar3: int=?,
unit
) => barObj = "";
external foo : barObj => t = "foo";
foo(makeBarObj(~bar1=5, ~bar2=3, ());
Is there, however, a simpler way of writing bindings for such functions? My problem with this approach is that it gets quite "long" when calling a function that takes in an options object, especially if it is a polymorphic argument, e.g.:
foo(`BarObj(makebarObj(~bar1=5, ~bar2=3, ())));
You can construct the object directly instead of using a separate function:
[@bs.val] external foo : Js.t({..}) => t = "";
let foo = (~bar1=?, ~bar2=?, ~bar3=?, unit) =>
foo({
"bar1": Js.Nullable.from_opt(bar1),
"bar2": Js.Nullable.from_opt(bar2),
"bar3": Js.Nullable.from_opt(bar3)
});
Which can be called with just
foo(~bar1=5, ~bar2=3, ());
But beware that this isn't exactly equivalent to what [@bs.obj] produces since properties being undefined are not always interpreted as not being defined.
If you need to pass it wrapped in a variant, you could have the object construction function wrap it. You can also usually define a set of functions instead:
fooWithString("bar");
fooWithOptions(~bar1=5, ~bar2=3, ());
Another hypothesis seems to be this one:
[@bs.obj]
external makeBarObj : (~bar1: string=?, ~bar2: int=?, ~bar3: string=?, unit) => barObj =
"";
[@bs.val] external foo : barObj => t = "foo";
let foo = (~bar1=?, ~bar2=?, ~bar3=?) => foo(makeBarObj(~bar1?, ~bar2?, ~bar3?, ()));
And then this way, the client of the API can simply call:
foo(~bar1=5, ~bar2=3, ())
It's basically the same thing as the solution presented in the question, but this hides the object conversion code in the library so that the client doesn't need to worry about it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With