另一个Javascript替代品: ReScript介绍

610 阅读10分钟

我们真的需要另一个吗?

CoffeeScript、TypeScript、PureScript,现在我们还有ReScript。诚然,它不是 "新的新的",但它是最近才出现的,而且它正试图取代古老的、由微软支持的TypeScript的位置。

那么你怎么看?我们是否需要另一个JavaScript替代品?我们是否应该停止玩弄这些语言,开始使用JS,接受它的缺陷和瑕疵?难道我们对每年都会出现的替代品不感到厌倦吗?

很显然,我们还没有。

ReScript是什么情况?

真的,它与所有替代品有什么不同?

就像他们中的许多人一样,它是一个关于强类型系统的JavaScript应该是什么样子的意见版本。根据他们的网站(以及我自己做的测试),这个类型系统是:

  • 比Typescript的更好,因为它更简单,而且是推断式的。是的,TS可以推断一些类型,但它并不鼓励你让它这样做。但是ReScript可以,而且他们的解释器在捕捉这些类型错误方面相当出色。
  • 静态的,因为它在运行时不被使用。如果你问我,这是对问题的过度简单化。但谁问过我?没有人。根据他们的说法,编译期间的静态推理是你所需要的,以确保你的代码不受那些讨厌的错误的影响。
  • 速度很快。在我用该语言进行测试后,我可以证明这一点。有了VSCode插件, 你所要做的就是保存文件,你会得到即时的反馈。

当然,他们的类型系统听起来很不错,但这并不是他们试图向你推销的TS更好的替代品的全部。还有一个事实是,他们并不试图成为JavaScript的超集,而是一个精心策划的功能列表。

这意味着他们将原始语言提炼成他们认为合适的东西(因此,有意见的部分)。在实践中,这意味着你没有类这样的结构,没有控制台这样松散的全局对象,也没有分号这样的东西(没错,他们终于解决了这个古老的争论:分号不需要,处理它)。

对于你来说,作为一个JavaScript(或TypeScript)的开发者,想要了解一个新事物意味着你必须重新学习语言。这不仅仅是用RS添加类型注解,你还必须重新学习所有东西的工作原理。这是不是太麻烦了?对于基本的东西来说并不是,特别是如果你也使用过其他语言,如Ruby或Python的话。

IF条件的括号不再需要了,IF的主体是一个表达式,返回最后执行的行。你可以把整个结构分配给一个变量,就像你在vanilla JS中使用三元操作符那样。

ReScript 在 JavaScript 方面有什么新特点?

作为一个JS开发者,你可以期望RS增加什么价值?这是个好问题。

让我们看看,除了推断类型系统外,你还有:

  • 管道,它是一种反向编写函数调用的方式。换句话说,如果你有myFunction(argument),你可以做argument->myFunction,从而模仿缺少的OOP方法。诚然,这只不过是句法上的糖,但这绝对是新的东西
  • 现在已经没有const了。事实上,让我换个说法:现在所有东西都是常量。或者换句话说,现在你用let声明你的变量,就像你在JS中用const声明一样。为什么不把let去掉呢?我不知道。然而,你可以用let重新定义变量,从而取代它的旧值,虽然不推荐(很明显!),但这是实现突变的一种方式。
  • 模式匹配。是的,RS将模式匹配添加到本来看起来很丑的switch语句中。事实上,现在它看起来更丑了,但至少你得到了一些有趣的功能。通过模式匹配,你可以测试记录/变量的形状而不是它们的值。鉴于任何旨在解决这个问题的OOP模式都不会被你利用,这是一个非常需要的功能。

为了清楚起见,我们正在声明一个具有特定形状的Teacher类型的记录(我将在第二部分解释记录),正如你所看到的,在开关里面还有一个叫做Student的记录类型。switch的模式匹配功能允许我们检查变量person1的形状,并根据我们是否在处理一个教师或一个特定的教师或其他东西做不同的事情。甚至在每个匹配块里面,你都可以把匹配的对象解构为变量,然后可以使用这些变量。

这绝对是一个强大的功能,正如我所说的,它是非常需要的,因为你不能声明多个类并在它们里面封装这种行为。

但除此之外,RS还带来了其他什么吗?当然有,一大堆已经知道的概念的重命名,让我们看看。

什么是新的,但实际上不是?

RS在重命名或改变我们处理旧概念的方式方面做得很好,以其强大的类型系统为名。

让我们来看看他们的一些瑰宝:

  • 图元。由于数组必须是类型化的,也就是说,它们里面只需要包含一种类型的变量,你可以定义一个元组,它是一个固定大小的数组,里面有任何东西。它也是不可变的和有序的。但是,它只是一个好的老数组,语言不会让你改变它的。
  • 记录。如果你曾经学过C语言,这就是你的结构。如果你曾经做过Javascript(翻白眼),那么这就是你的对象字面。我本来想说 "没有方法",因为他们的文档没有说明,但经过测试,你甚至可以给记录的属性分配函数,所以是的,这是你的对象字面。当然,它也是不可变的,但这就是创新的程度。
  • 变体。JavaScript没有Enum的概念,但是如果你尝试过其他语言(甚至是TypeScript),你会看到它们。它只是一个常量组的列表。这就是变体,另外一个例外是它的属性可以接收参数。比如说。

在上面的片段中,你可以看到我是如何比较两个分配了相同枚举值的变量的,然而由于它们收到了不同的参数(第6行和第7行),那么它们就不会相同。另一方面,如果你把val1和val2重新分配为NoValue,那么IF条件就会变成真。

这是一个革命性的概念吗?我不这么认为,说实话,还不足以值得采用一种新的语言。

  • 懒惰的价值。这是另一个对我来说没什么意义的概念。懒惰值 是一个代码块,你可以让它变得 "懒惰",因此你声明它,但它不会执行,直到你强迫它执行。当它最终执行时,它也会被缓存起来,所以下次你运行它时,它将返回缓存的值。老实说,这就是一个备忘函数,这就是它的全部内容。当然,有原生的记忆化功能是很好的,但话说回来,这并不是一个多么复杂的话题,把它藏在 "懒惰 "这样的概念后面对我来说毫无意义。

请注意,这些并不是坏的功能,它们要么是已经存在的解决方案的花哨名称,要么是不值得为获得新语言而学习的麻烦。

糟糕的部分

除了新语言的闪亮的外表之外,RS也有一些不好的地方,就像生活中的其他东西一样。

因此,让我们快速看看我在对该语言进行短期测试时发现的不好的部分。

  • 推断类型意味着没有 "真实 "的值。当然,这对你来说可能不是一个问题,但我真的很喜欢使用你能得到的隐式铸造到布尔值。在RS中,你需要确保你在IF语句中使用的表达式是一个布尔值。这绝对是一个小挫折,但还是一个挫折。
  • 脱离基本的东西是很复杂的。我围绕着类型推理和其他一些有趣的功能做了一些基本测试,一切都运行得很好。然后我有了一个绝妙的想法,从Node.js中导入一个模块,然后我花了2个小时试图理解它是如何工作的。后来我发现有一个不错的Node全局对象,你可以使用。嘿,活到老学到老,但如果我想导入一个不属于Node标准产品的外部库,那么我就得经历同样的磨练。你看,使用其他ReScript文件是相对简单的,但是导入已经在JS中完成的东西,男孩--哦--男孩,这是一个讨厌的语法。老实说,如果你创建了一种可以编译成JS的语言,是因为你希望你的用户能从现有的JS生态系统中受益,所以这部分应该更容易。
  • 错误信息并不那么好。而这就是我的原因。你可以有最疯狂的语法,用比萨饼的配料重命名已知的概念,我不在乎,但如果你希望人们使用你的语言,错误信息就必须清晰易懂。你认为下面这个错误信息是什么意思?

我个人不知道,因为:

  1. 我没有在那个地方写过一行代码。
  2. 它指的是什么论据,代码有好几个。

这个问题的答案是:我用let来定义Enum--我是说Variant--而不是用type关键字。显然,这不是我所期待的错误信息。

这是我最后一次尝试从Node.js导入fs模块。看到这个错误了吗?信息写着 "index out of bounds",那里没有代码!什么原因呢?

我相信精通ReScript的人一定能理解这个错误,但这不是一个好的开发者体验,它阻碍了采用,真的,它让我想回到JavaScript,简单明了。

ReScript会成为新的标准吗?

这个问题很难说,我不认为这很快就会发生,如果说最后一个错误信息的问题是什么的话。就目前的情况来看,这个问题对新人来说是个障碍,而不是帮助他们登上RS的马车。

此外,一个我还没有提到的小细节:这不是一个新项目。该语言目前是9.1版本,其网站也非常详细。老实说,向致力于记录一切的人(或一群人)致敬,那里肯定有很多细节。

然而,在9.1版本中仍然存在这些问题的事实告诉我,并没有很多人在使用它或关心它,以报告或帮助解决这些问题。

ReScript无疑显示了一些前景,它的一些想法也很有趣,然而,在与TypeScript相抗衡之前,该团队仍有许多地方需要改进。

你以前尝试过ReScript吗?现在你读到了关于它的报道,你会尝试吗?你还见过哪些其他类型的Javascript?请留下评论,让我们一起讨论