离开OCaml

2020-11-03 08:45:44

我在大约两周内构建了Python中的第一个Dark演示。几个月后,当我开始制作它时,我在OCaml中重建了它。早在2017年,当我在考虑Dark使用的语言和平台时,OCaml非常令人信服:

它是一种具有静态类型的高级语言,因此当我们弄清楚语言/产品是什么时,很容易进行大规模更改。

您主要使用SUM类型对数据建模,在我看来,这是对数据建模的最佳方式。

它与我想要构建的语言非常相似(特别是,我们可以对Dark的值重用内置的不可变数据结构)。

它有高性能的名声,这意味着我们可以为Dark编写一个解释器,而不会让它变得非常慢(而不是用Python编写解释器,后者可能太慢了)。

不幸的是,当我们建造黑暗的时候,我们遇到了严重的问题,这使得在OCaml中建造变得具有挑战性。

当您押注于一种非主流语言时,您接受的一件事是许多库将不会可用。当有一个很小的社区时,通常没有足够的人从事这种语言的工作,无法建立重要的库。如果很少有人构建业务应用程序,这一点尤其正确。

OCaml中有许多高质量的库,特别是用于数据结构和数据操作的库。一年一度的简街代码转储非常有用,而且质量非常高。然而,我们确实感觉到缺少几个图书馆。其中最明显的是,我们必须自己构建Unicode字符串库(构建在Daniel Bünzli构建的非常令人印象深刻的OCaml Unicode库之上),但我们需要更多的库。

缺少Google Cloud的SDK对我们影响很大。当你在寻找适合市场的产品时,你做的是最简单、最容易的事。如果您的云提供商缺少一个好的SDK,那么最简单、最容易的事情往往是糟糕的架构选择。我们已经在我们的数据库之上构建了我们自己的队列,而不是使用GCP上提供的生产质量的云队列。同样,我们几乎不使用云存储(GCP';的S3版本),因为我们最初将内容放入数据库是因为它更容易。我们已经构建了3个服务,2个在Rust中,1个在Go中,以解决我们所面临的挑战。

这里最大的挑战是我们使用Postgres。Postgres是一个很棒的数据库,我们都是它的忠实粉丝,但是Cloud SQL不是一个很好的托管数据库。GCP的立场是,Cloud SQL是用来勾选的,我们应该使用Cloud Spanner。我很想换成云扳手,但我们OCaml没有驱动程序。考虑到OCaml中的Postgres驱动程序还不是特别成熟,很难指望会有Cloud Spanner驱动程序存在,而且确实没有。我们不得不为OCaml Postgres驱动程序做贡献,而且我们的代码库中的某些部分在处理该驱动程序不支持的功能时已经完全损坏了。

我们还面临着缺乏高级别的生产性Web堆栈的问题(有一些声誉良好的低级堆栈我一直在努力使用,还有一些新的堆栈看起来不错),尤其是缺乏用户身份验证模块。我们现在一直在使用Auth0来解决这个问题,它有比我想要的更多的移动棋子,而且成本高得令人震惊(我们的7000名用户,其中大多数从未登录,花费我们超过500美元/月)。

我们已经解决了其他缺失的供应商SDK,直接调用它们的HTTP端点,这基本上没什么问题。然而,对于像Encryption这样的库,我们没有这样的选择-我们破解了一个丢失的加密库,但决定在我们对其进行安全审计之前不将其交付生产(这实际上从来都不值这个成本)。

在CircleCI,我们押注于Clojure。这也是一种非主流语言,但它调用JavaSDK的能力意味着我们拥有一个成熟的云库,这对于构建CircleCI至关重要。当然,在OCaml中,我们可以调用C库(甚至可能还有Rust库),但它不能与我们可以直接调用的本地库相匹配。

我主要是支持任何人都可以学习任何语言的阵营,但我看到一个团队在与OCaml斗争,这是有充分理由的。与其他语言相比,OCaml中的语言教程非常差;它们大多是学术课程的课堂讲稿。

当然,与Rust或Elm(这两个都曾经在我们的堆栈中)相比,编译器并不是特别有帮助。通常,它不提供有关错误的信息。语法错误通常显示为语法错误,尽管它会尝试为不匹配的花括号(通常是不正确的)提供正确的错误。打字错误可能会成为阅读的真正负担,即使在使用了3年之后也是如此。

OCaml中的文档通常很难找到。在过去的几年中,Jane Street文档有了很大的改进,但即使是找出特定模块中的哪些功能对于大多数库都是可用的,这也可能是一个挑战。与Rust中优秀的docs.rs相比,Rust中的每个包都有全面的API文档。

我个人在OCaml奋斗的方式之一就是围绕路易斯安那州立大学(LWT)。LWT是(其中之一!)。OCaml&39;的异步实现。几年前我想不出来,所以就构建了一个单线程服务器。我们因这一决定而遭受的变通和停机时间是巨大的。关于构建高性能(甚至中等性能!)的教程。Web服务器将非常有价值。

工具是我在OCaml中读到的很好的东西。我记得读到过有一个调试器可以回到过去!我不知道它到哪里去了,但我从来没有听说过有人用过它。

我们一直在努力让编辑器工具为我们工作。这在一定程度上是因为我们也使用了ReasonML,这似乎会破坏一些东西。不幸的是,这在编程中很常见,但在小型社区中更是如此:您可能是第一个尝试使用特定配置的人。

最后,各种工具之间的脱节是巨大的。你需要了解Opam,Dune和Esy,才能让一些东西正常工作(你也可以在没有Esy的情况下做到这一点,只依靠Opam,但那要糟糕得多)。我在这里谈到了一大堆这样的挑战。

多核现在随时都会出现,™️,虽然这对我们来说不是什么大事,但它很烦人。

我最大的烦恼之一是OCaml的人们经常谈论Fancy Type系统问题,而不是如何实际构建产品和应用程序。在其他类似语言的社区(ReasonML、Elm、F#),人们谈论构建应用程序和解决他们的问题。在OCaml中,感觉人们花了大量时间讨论函数器。这并不完全是我在哈斯克尔世界中感受到的水平,但它指出,构建生态系统核心的人并不存在与我相同的问题(即构建基于网络的东西)。

老实说,我认为OCaml在一开始就是一个很好的选择。能够快速、安全地对您的应用程序进行大规模更改是静态类型函数式语言所擅长的。我很高兴我们做出了这个选择,回想起来,这似乎仍然是我们当时拥有的最好的选择。

我正在努力建立下一个版本的后端。我们大约有两万行要替换,它们将在保持语义不变的情况下用一种新的语言重写。我计划将前端保留在ReasonML中:它不会因为可以很好地与JS接口而遭受相同的库问题,而且它有近50000行代码,所以它将是一项更大的事业。

你可以在这里报名参加“黑暗”。欲了解更多关于Dark的信息,请关注我们的RSS,在Twitter上关注我们(或我),加入我们的松弛社区,或观看我们的GitHub回购。