巴别塔@ 7的管道运营商历险记


babel@7.0.0-beta52发行版为@babel/plugin-proposal-pipeline-operator 提供了一个新的必需配置标志,这破坏了该插件先前版本的向后兼容性。 在本文中,您将学习什么是pipeline运算符以及为什么需要配置。


UPD:智能管道出现在babel@7.2.0: https ://babeljs.io/blog/2018/12/03/7.2.0#smart-pipeline-operator-parsing-8289-https-githubcom-babel-babel- 拉8289


现况


最初提出 pipeline运算符的吉尔伯特·加萨Gilbert Garza)着手获得一种简单的语法,以“以可读的函数样式编写有序的函数调用链”。 管道运算符起源于F#,Hack,Elm,Elixir等语言,当将其添加到JavaScript时,会出现两个有争议的问题:


  • 在哪里以及如何使用占位符?
  • async / await如何在管道中async / await

占位符


凯文•史密斯Kevin Smith)这张票中提出了第一个问题,他建议使用哈克语言管道 风格 。 在Hack中,占位符对于管道的任何右侧都是必需的,例如:


 namespace Hack\UserDocumentation\Operators\Pipe\Examples\MapFilterCountPiped; function piped_example(array<int> $arr): int { return $arr |> \array_map($x ==> $x * $x, $$) |> \array_filter($$, $x ==> $x % 2 == 0) |> \count($$); } var_dump(piped_example(range(1, 10))); 

我们以此为基础,可以在任何表达式中使用占位符,并且占位符来自最后一个管道步骤。 这种方法为我们提供了灵活性和充足的机会来编写表达式。


硬币的另一面是由于添加了新令牌导致语言的复杂性。 到目前为止,我们选择了哈希( # ),尽管讨论仍在进行中,但任何令牌都可能与其他用途有交叉之处。 例如,散列也由该类私有字段使用,就像仍然使用任何其他令牌变体一样。


异步/等待


pipeline语句的第一个版本包含以下用于await语法:


 x |> await f 

可以部署到:


 await f(x) 

不幸的是,用户可能会期望这样的部署:


 (await f)(x) 

虽然向pipeline添加async想法已经破灭,但委员会成员反对不支持async / awaitpipeline运营商。 是的,对于如何使用无需显式语法返回Promise的函数,有一些选项,但是所有这些选项都太麻烦或需要辅助函数。


建议的解决方案


讨论的结果是,形成了两个建议(除了最小选项之外):使用F#管道和智能管道。 让我们看看这些建议。


最小操作员选项


此优惠仅适用于基本功能。 在最低版本中,删除了对异步的支持,并且没有占位符。 该选项与配置出现之前的先前版本的babel插件的行为相对应,并且与存储库中pipeline操作员的当前规范相对应。 它更多地用作确定其他提案的利弊的探针草案,并且如果没有替代提案中的根本性更改,就不太可能被接受。


F#管道


根本不需要F#管道的占位符。 在基本版本中,箭头函数基于每个人都熟悉的ES2015语法,涵盖了对占位符的需求,所需的书写较少。


此刻(根据F#线的规范),箭头功能应放在方括号中:


 let person = { score: 25 }; let newScore = person.score |> double |> (_ => add(7, _)) |> (_ => boundScore(0, 100, _)); 

正在进行调查以确定使用不带括号的箭头功能是否可行,此处在语法上看起来是多余的。


至于异步, await在F#管道中用作一元函数:


 promise |> await 

发生的事情:


 await promise 

因此await可以在一长串异步调用的中间使用:


 promise |> await |> (x => doubleSay(x, ', ')) |> capitalize |> (x => x + '!') |> (x => new User.Message(x)) |> (x => stream.write(x)) |> await |> console.log; 

这种特殊的await处理可能会潜在地打开使用其他一元运算符(例如typeof )的类似可能性,但是F#管道的原始规范不包含它们。


智能管道


Smar管道将占位符的概念带到了逻辑上的结论,允许在管线中使用部分使用和任意表达。 前面的长链可以这样写:


 promise |> await # |> doubleSay(#, ', ') |> # || throw new TypeError() |> capitalize |> # + '!' |> new User.Message(#) |> await stream.write(#) |> console.log; 

在智能管道中使用占位符的规则非常简单。 如果将单个标识符传递到管道步骤,则不需要其他令牌(占位符),这称为“裸样式”


 x |> a; x |> fb; 

与Hack不同,一元函数不需要占位符。


对于其他表达式,需要一个占位符(称为“词法主题标记”),并且认为管道可以在“主题样式”- “主题样式”内工作 。 在这种情况下,缺少占位符标记会导致早期的SyntaxError错误:


 10 |> # + 1; promise |> await #; 

如果有任何运算符,方括号(包括用于调用方法的内容),引号或除标识符和点之外的其他任何内容,则需要使用占位符标记。 这将有助于避免被脚踩开并消除不确定性。


智能管道以更通用的方式解决了支持异步的问题,这使我们能够在管道中使用所有可能的表达式,不仅可以使用await ,还可以使用typeofyield和其他任何运算符。


巴别塔进入现场


一旦将所有三个提案具体化,我们就得出结论,这种讨论不会导致解决提案之间的深刻矛盾。 我们认为最好的方法是使用真实代码中的句子收集开发人员的反馈。 考虑到Babel在开发人员社区中的角色,我们决定将所有三个选项添加到pipeline操作符插件中。


由于babylon三个句子的解析略有不同,但有所不同,因此必须首先将它们的支持添加到@babel/parser (即babylon )中,并且解析器必须知道现在应该支持哪个提议。 因此, pipeline操作员插件需要"proposal"选项,用于配置巴比伦进行解析和后续转换。


我们在线上进行此工作是因为我们需要进行所有更改,以破坏向后兼容性,直到babel @ 7不再是beta。 最后,我们希望使插件的管道选项之一成为默认选项,以消除对配置选项的需求。


考虑到这些限制,我们决定在插件配置中添加一个选项并使其成为必需,从而迫使用户确定他们要在项目中使用哪些商品。 一旦选择了一个特定的建议作为操作员的规范行为,我们便将选项"proposal"标记为过时,并且该规范选项将默认运行。 对已取消优惠的支持将一直持续到下一个主要版本。


参加


如果您想参与提案的讨论,那么所有讨论都是公开的,您可以在管道运营商的提案存储库中找到它们。 TC39会议的演讲将为您服务。 最后,您可以在Twitter上关注James DiGioiaJS ChoiDaniel Ehrenberg


但更重要的是,一旦pipeline上的工作完成,请在您的项目中尝试一下! 我们还在努力为repl添加新功能,以便您可以交互式检查代码。 我们需要反馈,并且在实际代码中使用它确实有助于组装。 将推发布@babeljs

Source: https://habr.com/ru/post/zh-CN418125/


All Articles