绑定带有选项参数的函数
Bindings for functions with options parameter
在 JavaScript 中有一个接受选项参数的函数是常见的做法,如下所示:
function foo({ bar1, bar2, bar3 }) {}
foo({ bar1: 5, bar2: 3 })
在 Reason/OCaml 中,人们更愿意为这些函数使用带标签的参数:
let foo = (~bar1, ~bar2, ~bar) => {}
foo(~bar1=5, ~bar2=3, ())
现在,我知道有这种方法可以为这些函数创建 Reason/Bucklescript 绑定:
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, ());
但是,是否有更简单的方法来为此类函数编写绑定?我对这种方法的问题是,当调用一个接受选项对象的函数时,它变得相当 "long",特别是如果它是一个多态参数,例如:
foo(`BarObj(makebarObj(~bar1=5, ~bar2=3, ())));
您可以直接构造对象而不是使用单独的函数:
[@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)
});
只需
即可调用
foo(~bar1=5, ~bar2=3, ());
但请注意,这并不完全等同于 [@bs.obj]
产生的结果,因为 undefined
的属性并不总是被解释为未定义。
如果您需要将其包裹在变体中传递,您可以让对象构造函数将其包裹起来。您通常也可以定义一组函数来代替:
fooWithString("bar");
fooWithOptions(~bar1=5, ~bar2=3, ());
另一个假设似乎是这个:
[@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?, ()));
然后这样,API 的客户端可以简单地调用:
foo(~bar1=5, ~bar2=3, ())
与问题中的解决方案基本相同,只是将对象转换代码隐藏在库中,客户端无需担心。
在 JavaScript 中有一个接受选项参数的函数是常见的做法,如下所示:
function foo({ bar1, bar2, bar3 }) {}
foo({ bar1: 5, bar2: 3 })
在 Reason/OCaml 中,人们更愿意为这些函数使用带标签的参数:
let foo = (~bar1, ~bar2, ~bar) => {}
foo(~bar1=5, ~bar2=3, ())
现在,我知道有这种方法可以为这些函数创建 Reason/Bucklescript 绑定:
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, ());
但是,是否有更简单的方法来为此类函数编写绑定?我对这种方法的问题是,当调用一个接受选项对象的函数时,它变得相当 "long",特别是如果它是一个多态参数,例如:
foo(`BarObj(makebarObj(~bar1=5, ~bar2=3, ())));
您可以直接构造对象而不是使用单独的函数:
[@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)
});
只需
即可调用foo(~bar1=5, ~bar2=3, ());
但请注意,这并不完全等同于 [@bs.obj]
产生的结果,因为 undefined
的属性并不总是被解释为未定义。
如果您需要将其包裹在变体中传递,您可以让对象构造函数将其包裹起来。您通常也可以定义一组函数来代替:
fooWithString("bar");
fooWithOptions(~bar1=5, ~bar2=3, ());
另一个假设似乎是这个:
[@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?, ()));
然后这样,API 的客户端可以简单地调用:
foo(~bar1=5, ~bar2=3, ())
与问题中的解决方案基本相同,只是将对象转换代码隐藏在库中,客户端无需担心。