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, ());

然而,有没有一种更简单的方法来为这些函数编写绑定?我对这种方法的问题是,当调用一个接收选项对象的函数时,它会变得相当“长”,特别是如果它是一个多态参数,例如:

foo(`BarObj(makebarObj(~bar1=5, ~bar2=3, ())));
4

2 回答 2

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]产生的结果,因为属性 beingundefined并不总是被解释为未定义。

如果您需要将它包装在一个变体中传递,您可以让对象构造函数包装它。您通常也可以定义一组函数:

fooWithString("bar");
fooWithOptions(~bar1=5, ~bar2=3, ());
于 2018-01-13T13:37:47.653 回答
1

另一个假设似乎是这个:

[@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, ())

它与问题中提出的解决方案基本相同,但是这将对象转换代码隐藏在库中,以便客户端无需担心。

于 2018-01-13T23:36:59.557 回答