在 ReasonML 中的最后一个管道之后使用快速管道运算符编译错误

Compile error using fast pipe operator after pipe last in ReasonML

将 "fast pipe" 运算符与 many places 中的 "pipe last" 进行比较的方式暗示它们是彼此的直接替代品。想要将一个值作为函数的最后一个参数发送?最后使用管道 (|>)。想把它作为第一个参数发送?使用快速管道(曾几何时 |.,现在已弃用 ->)。

因此,您可能会像我直到今天早些时候那样认为以下代码会为您提供正则表达式匹配中的第一个匹配项:

Js.String.match([%re "/(\w+:)*(\w+)/i"], "int:id")
|> Belt.Option.getExn
-> Array.get(1)

但你错了(再说一次,就像我今天早些时候...)

相反,编译器发出以下警告:

We've found a bug for you!
OCaml preview 3:10-27
This has type:
  'a option -> 'a
But somewhere wanted:
  'b array

参见this sandbox。给出了什么?

看起来他们搞砸了 -> 的优先级,所以它实际上被解释为

Js.String.match([%re "/(\w+:)*(\w+)/i"], "int:id")
|> (Belt.Option.getExn->Array.get(1));

内联运算符:

Array.get(Belt.Option.getExn, 1, Js.String.match([%re "/(\w+:)*(\w+)/i"], "int:id"));

或者更明确地使用部分应用程序,因为 Reason 的语法在柯里化方面有点混乱:

let f = Array.get(Belt.Option.getExn, 1);
f(Js.String.match([%re "/(\w+:)*(\w+)/i"], "int:id"));

|. 替换 -> 有效。就像用 |..

替换 |> 一样

我认为这是 Reason 中的一个错误,但在任何情况下我都建议不要使用 "fast pipe",因为它会引起很多混乱而带来的好处很少。

另请参阅此 discussion on Github,其中包含各种解决方法。将@glennsl 保留为可接受的答案,因为它描述了问题的性质。

更新:还有 an article on Medium 深入探讨了 "data first" 和 "data last" 的优缺点,特别是因为它适用于 Ocaml / Reason with Bucklescript。