首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >具有固定字符串值的配置的ReasonML绑定函数

具有固定字符串值的配置的ReasonML绑定函数
EN

Stack Overflow用户
提问于 2019-03-24 23:31:23
回答 2查看 583关注 0票数 3

假设我在Javascript中有这个函数,它可以根据适当的配置生成字符串:

代码语言:javascript
复制
function func(config) {
  // ...
}

另外,让我们假设config变量具有如下结构(所有这些都可以不提供给函数调用):

代码语言:javascript
复制
{
  "color": string,  // can be: "blue", "red", "green"
  "number": int,    // can be: any number
  "other": string,  // can be: "x", "y"
}

如何为此创建正确的绑定?我被困住了:

代码语言:javascript
复制
[@bs.deriving abstract]
type options = {
  [@bs.optional]
  color: [@bs.string] [ | `blue | `red | `green ]
  [@bs.optional]
  number: int,
  [@bs.optional]
  other: [@bs.string] [ | `x | `y ]
}

[@bs.module]
external func: options => string = "func";

但是,当尝试像这样使用时,它不起作用:

代码语言:javascript
复制
let config = MyModule.config(
  ~color=`blue,
  ~number=123,
  ~other=`x
);

let value = MyModule.func(config);

colorother值是整数,而不是字符串。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-03-26 02:00:48

这是一个用于命名参数(具有可选字段的对象)的JavaScript习惯用法,需要适应OCaml/ReasonML习惯用法(具有实际标记的参数的函数)。您将通过三个步骤来完成此操作。如Glenn所示,第1步为配置定义外部:

代码语言:javascript
复制
type config;
[@bs.obj] external config: (
  ~color:[@bs.string] [`blue | `red | `green]=?,
  ~number:int=?,
  ~other:[@bs.string] [`x | `y]=?,
 unit,
) => config = "";

步骤2,使用配置对象的JavaScript样式绑定到JavaScript函数:

代码语言:javascript
复制
[@bs.val] external func: config => string = "";

步骤3,使用带标签的参数将JavaScript函数绑定包装在一个OCaml惯用函数中:

代码语言:javascript
复制
let func(~color=?, ~number=?, ~other=?, ()) = ()
  |> config(~color?, ~number?, ~other?)
  |> func;

你可以这样使用它:

代码语言:javascript
复制
let result = func(~color=`blue, ());
票数 1
EN

Stack Overflow用户

发布于 2019-03-26 00:20:26

@bs属性通常是未经深思熟虑的技巧,您不应该期望它能很好地与其他属性一起工作,或者真正地与文档所解释或显示的示例之外的任何东西一起工作。然而,如果一个属性被用在了不想使用的地方,你通常至少会得到一个关于该属性未被使用的警告,你的代码就是这么做的。

特别是@bs.string只适用于外部变量最外层的类型,即其值将被直接传递给外部函数的类型。还有一种使用外部函数创建JavaScript对象的方法,这种方法使用的魔力更少,让您可以更好地控制API。据我所知,与@bs.deriving相比,唯一的缺点是不能使用像@bs.as这样的东西覆盖字段名。它们必须是有效的OCaml标识符。

下面是使用带有@bs.obj注释的外部函数实现的示例

代码语言:javascript
复制
type options;
[@bs.obj] external options : (
  ~color:[@bs.string] [`blue | `red | `green]=?,
  ~number:int=?,
  ~other:[@bs.string] [`x | `y]=?,
  unit
  ) => options = "";

要使用它,您可以使用与@bs.deriving完全相同的名称

代码语言:javascript
复制
let config = options(~color=`blue,~number=123, ~other=`x, ());

但即使这样,我也遇到了一些边缘情况,传入的是整数值,而不是字符串。出于这个原因,我倾向于完全避免使用多态变体属性,而是使用普通变体以及转换函数。这还有一个额外的好处,那就是更加地道,更好地融入其中,并且与非BuckleScript代码更具互操作性。

下面是使用这种方法的示例:

代码语言:javascript
复制
type color = Blue | Red | Green;
let colorToString = fun
  | Blue => "blue"
  | Red => "red"
  | Green => "green";

type other = X | Y;    
let otherToString = fun
  | X => "x"
  | Y => "y";

[@bs.obj] external options : (
  ~color:string=?,
  ~number:int=?,
  ~other:string=?,
  unit
  ) => options = "";

[@bs.module] external func: options => string = "func";

let func = (~color=?, ~number=?, ~other=?, ()) =>
    func(options(
      ~color = ?Belt.Option.map(color, colorToString),
      ~number?,
      ~other = ?Belt.Option.map(other, otherToString),
      ()));

let config = func(~color=Blue,~number=123, ~other=X, ());
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55325408

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档