ReasonML与Elm的比较

34

我在StackOverflow看到了这个ReasonML vs TypeScript的问题,现在我想知道ReasonML和Elm相互之间的比较。

它们之间有哪些相似点和不同点? 我应该何时使用哪种语言?一个优于另一个的优势是什么?


1
这是一个非常广泛的问题;请投票关闭。 - Onorio Catenacci
3
如果此问题被标记为javascript,它肯定会被关闭。但是我注意到广泛的elm问题通常保持开放状态,甚至得到很好的答案(比如@glennsl的回答)。 - Sidney
这仍然是一个非常广泛的问题,不管是否标记为javascript。如何询问“在什么情况下应该使用哪种语言?”(涉及任何两种语言),却不引发很多意见呢? - Onorio Catenacci
2
这不是适合在StackOverflow上发布的内容。但它是一个有趣的补充(尽管很广泛),所以我会让它通过。 - Sean Francis N. Ballais
3
这是一个显然不适合在Stack Overflow上提问的糟糕问题,因为它涉及软件工程并且原本自然适合的程序员领域已不再可行。这很遗憾,因为这是一个有趣的问题。简单的答案是(我无法提供)Reason是一种通用语言,而Elm非常明确地专注于前端客户端应用程序,并将此限制视为积极的(并反映出目的本身就是其自身的限制)。 - Murph
2
请注意与此仍然开放的问题的相似之处:https://dev59.com/UWMl5IYBdhLWcg3wbGl1?rq=1 - icc97
1个回答

86

我对Elm并不是很熟悉,但我稍微了解了一下,对Reason比较熟悉,所以我会试着帮忙。我相信这里会有一些不准确的地方,请不要将我所说的作为事实,而应该将其作为指向你自己更详细了解的提示。

Elm和Reason都是具有非常相似编程模型的类ML语言,因此我将重点介绍它们之间的区别。

语法:

Elm使用Haskell风格的语法,它被设计(或者演化)用于Elm和Reason所使用的编程模型,因此一旦你熟悉它,阅读和编写惯用代码时应该非常顺畅,但对大多数程序员来说,它看起来非常不同和陌生。

Reason试图通过尽可能模拟JavaScript的语法来使其更易接近,这对于大多数程序员来说都很熟悉。然而,它也旨在支持底层OCaml语言的整个功能集,这使得某些函数式模式相当笨拙。

其中一个例子是函数应用语法,在Elm中强调了函数的柯里化性质(f a b),非常适合组合函数并构建可读的DSL。 Reason使用括号语法(f(a, b))隐藏了这种复杂性,这使得它更容易进入(直到你意外地被绊倒,因为它当然仍然不同),但是会让大量使用函数组合的语句需要用大量的括号。

可变性:

Elm是一种纯函数语言,理论上很好,但在实践中挑战很大,因为周围的世界对Elm追求纯粹性的努力不太关心。我认为,Elm首选的解决方案是通过在JavaScript中编写有问题的代码来隔离不纯性,然后通过Web组件或端口在Elm中访问它。这意味着您可能需要在一个单独且非常不安全的语言中维护大量的代码,并连接它们所需的大量样板文件,同时还需要弄清楚如何将圆形物体适配到端口等方面。
另一方面,Reason则更加“实用主义”,我喜欢称之为这样。您会为了增加生产力和短期利益而牺牲一些安全性、理想和长期利益。在Reason中隔离不纯性仍然是一个好的实践,但您不可避免地会走捷径来完成事情,这会在以后给您带来麻烦。
但即使您设法足够自律地隔离所有不纯性,您仍然需要付出代价才能在语言中进行突变。其中一部分代价就是所谓的值限制,您迟早会遇到它,并且它会让您感到困惑和愤怒,因为编译器无法证明在某个时刻不可能涉及可变引用而拒绝直观上应该工作的代码。
JavaScript互操作性:
如上所述,Elm通过端口和Web组件提供了与JavaScript互操作的能力,这些功能是故意限制的。以前可以使用本地模块,它们提供了更多的灵活性(和可能导致问题的能力),但这种可能性正在消失(至少对于普通人来说),这一举措在哲学上并不令人惊讶,但也引起了争议。在此处阅读更多关于此变化的信息 Reason或者说BuckleScript提供了丰富的基元,可以直接绑定到JavaScript,并且很常见地生成符合惯用法的Reason接口,而无需编写任何粘合代码。虽然不是非常直观,但一旦理解就很容易做到。但是,如果做错了,稍后某个随机点可能会出现问题。您必须编写一些粘合代码才能提供良好的惯用API,可以使用所有安全保证的Reason来编写,而不必编写不安全的JavaScript。
生态系统:
由于Elm的JavaScript互操作性有限,因此生态系统相当小。没有太多优质的第三方JavaScript库可提供Web组件,自己实现需要大量的工作。因此,您将看到库直接在Elm本身中实现,这当然需要更多的努力,但通常会产生更高的质量,因为它们是专门为Elm设计的。
工具链:
Elm因其出色的错误信息而闻名。尽管Reason也在努力,但在很大程度上并不如此。至少部分原因是因为Reason本身并不是编译器,而是建立在OCaml编译器之上,因此可用信息有限,可能出现的错误面积非常大。但它们也没有经过深思熟虑。
Elm还拥有一个伟大的打包工具,可以为您设置一切,并检查您发布的软件包的接口是否已更改以及版本号是否符合语义化版本控制。Resaon/BuckleScript只使用npm,并要求您手动管理所有Reason/BuckleScript特定的内容,例如使用新依赖项更新bsconfig.json。
Reason、BuckleScript、它的构建系统和OCaml都非常快。我还没有遇到任何项目需要超过3秒才能从头开始编译,包括所有依赖项,增量编译通常只需要几毫秒(尽管这并不完全没有成本)。据我所知,Elm的性能不如此高。
Elm和Reason都有格式化工具,但Reason格式化的代码质量显着较差(尽管正在缓慢改善)。我认为这主要是因为它必须处理的语法复杂得多。
成熟和衰败:
Reason是基于OCaml构建的,具有20多年的历史,因此拥有经过实战检验和长时间证明有效的坚实基础。此外,它是由学术界大力发展的语言,这意味着某个功能可能需要一段时间才能得到实现,但是一旦实现了,它就非常可靠,因为它基于理论甚至可能已被正式证明。不足之处在于,它的年龄和实验性质也意味着它积累了一些难以摆脱的过时内容。
另一方面,Elm相对较新,管理不那么繁琐,可以更快地移动,并且不害怕与过去决裂。这使其更加简洁连贯,但类型系统也不那么强大。
可移植性:
Elm编译成JavaScript,本身就非常便携,但目前仅限于浏览器,特别是Elm架构。这是一个选择,而且将其定位于node或平台也不会太困难。但反对这种做法的论点是,它会分散注意力,从而使其在其专业领域的表现不佳。
Reason基于OCaml,实际上首先目标是本机机器代码和字节码,但也有JavaScript编译器(或两个),使其能够针对浏览器、node、electron、react native,甚至能够编译成unikernel。不过据说Windows支持有点靠不住。作为一个生态系统,Reason首要目标是React,但也有一些库可以很自然地使用Elm架构

治理:

Elm由一名单独的开发者设计和开发,他能够清晰地传达他的目标和推理,并且全职工作。这使得最终产品具有连贯性和良好的设计,但是开发速度较慢,而巴士因素可能会使投资变得困难。

Reason的故事稍微复杂一些,因为它更像是一个项目集合的伞头名称。

OCaml是在公开管理、设计和开发的,主要由学者和各种基金会和商业支持者赞助的开发者开发。

BuckleScript是一种JavaScript编译器,源自于OCaml编译器,由一名开发者开发,他的目标和就业情况不明确,并且不费心解释他的推理或决策。虽然PR被接受,但缺乏解释和晦涩的代码库使其实际上是封闭式开发。不幸的是,这也不会导致特别连贯的设计,而巴士因素可能也会使投资变得困难。

Reason本身和ReasonReact由Facebook管理。PR受到欢迎,大量的Reason开发由外部驱动,但大多数决策似乎是在某个后房间做出的。除了微不足道的错别字修正等之外,对ReasonReact的PR经常被拒绝,可能有很好的理由,但通常没有太多解释。然后,更好的设计通常会在后房间中随着时间的推移得以出现。


1
我认为Bucklescript是由彭博支持的? - Madsn
3
这个仓库已经从彭博公司转移到了一个独立的组织,据我所知,开发者不再受雇于彭博公司,已经从纽约搬回中国。而且,在BuckleScript网站上,彭博公司甚至没有被列为用户。因此,我认为他们不再提供多少支持了。 - glennsl
感谢您的回答。我想补充一点,Elm 在 DOM 操作方面非常高效,但在编译速度方面是否快速,我无法评论,因为我没有进行基准测试,也没有查阅相关文献。除非进行基准测试,否则很难做出明确的评估。 - BenKoshy
@BKSpurgeon Elm 0.19 显著提高了编译时间。BuckleScript 仍然更快,但从主观经验来看,我至少在一个 10k 行的 Elm 0.19 项目中没有遇到编译速度方面的问题。 - glennsl
1
很棒的文章!虽然我有一些 Elm 的经验,但我对其中一个观点持不同意见,即官僚主义:Elm 是一个小项目,基本上由一个人运行。但它有着令人印象深刻的能力,可以模拟钙化全球财团的功能障碍。这是一个单人 IBM 级别的灾难,不断更改 Github 组织的名称,项目的洗牌、合并、拆分、关闭-无法修复、关闭-修复但未能解决问题以及忽略问题,废弃前一个版本中的重要功能特性,在替代方案出现之前删除所需的功能(Websockets)等。 - Matthias Winkelmann

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接