作者 | Paul Biggar
以下为译文:
我们编写了一门语言,其中集合了编程语言、结构化编辑器以及基础设施等所有功能,我们的目标是将构建后端服务的难度降低100倍。
我们的这门语言采用了F#,很多人都对此表示很惊讶,包括我在内。多年来,我们一直在讨论如何使用 Rust 重写我们的代码,我们有一个用 Rust 编写的命令行工具和两个服务,所以我一直坚信我们会采用 Rust。
为什么不选择Clojure / Haskell / Scala?
常常有人问我们为什么不选择其他几种语言,所以我先来介绍一下我们将它们排除在外的原因。
1、Clojure
我有很多使用Clojure的经验,因为CircleCI几乎都是用Clojure编写的。但是,我们花费了大量时间来处理“意外情况”,特别是“这个字段是什么类型?”,以及遍布各处的null。因此,我故意没有选择使用动态类型的语言,尽管Clojure是一门讨人喜爱的语言。此外,我们还可以避免Clojure社区对Rich Hickey(Clojure的作者)的崇拜。听完他的题为“Maybe Not”(https://www.youtube.com/watch?v=YR5WdGrpoug)的演讲后,我更加坚定地认为动态类型的水太深,而且我十分不同意对动态类型的看法。
2、Haskell
我曾经非常努力地尝试Haskell,还曾尝试编写Haskell的解释器,但我还是不太喜欢这门编程语言。下列用户的留言说出了我的心声:
我认为,Haskell 社区太过于学术化。最近 Haskell 库的邮件列表中有一篇帖子表示:
“在一次私人交流中,有人向我指出,元组函数\x->(x,x) 实际上是对双应用和一些相关结构进行单子形式的对角化的特殊情况。”
3、Scala
我没有使用Scala的经验,但是我感觉这门语言及其社区都是一团糟。所以我没有予以考虑,而且现在也不会。
为什么没有选择Rust?
优秀的工具
优秀的库生态系统
优秀的社区
-
优秀的宏(尽管我感觉为了解决语言本身的问题,我有点过度使用宏)
在做最终决定的时候,导致我没有选择Rust的主要因素包括:缺少GCP库,以及语言本身太接近底层。
1、库
Rust 有数不尽的库,而且运行良好,集成得也很好。Rust 拥有 Honeycomb、LaunchDarkly 以及 Rollbar 等第三方库,这些库对我们的服务来说非常重要。然而,GCP 的库似乎非常草率。它是自动生成的,而且种种问题表明在这项技术上他们已经黔驴技穷。鉴于我们想要一个更加丰富的库生态系统,选择 Rust 似乎非常冒险。
2、异步
最近,我刚刚得到了 Rust 性能测试的同步版本。于是,我尝试将其异步化。然而,我却发现异步的难度太大了。显然,递归会导致异步的复杂度加剧,但最终导致我崩溃的是 Pinning。
下面,我来介绍一下详情。在使用 tokio 运行时编写异步的多线程服务器时,你可以在线程之间移动异步进程。这意味着你可以复制内存,因此你需要 pin?算了,我只记得这么多。代码在这里(https://github.com/darklang/fizzboom/blob/main/rust-hyper-async/execution-engine/src/eval.rs),我相信有人能更好地解释这个问题。
我曾努力尝试解决这个问题,但最后证明只是白白浪费时间。显然,这类的boxing和pining只能在没有GC的时候使用;在拥有GC的情况下,你根本不需要理会。而这就成了我的最后一根稻草。
3、Rust是一种低级语言
我正在实现的语言本质上就是F#/OCaml,因此使用F#/OCaml实现理应更加容易。有人指出,我在尝试用Rust编写OCaml,但Rust的设计初衷并非如此,我认为这话没错。Rust的语义简化了很多工作,但不适用于我的工作。
我认为我们大多数人都不需要Rust。我认为Rust拥有一个很棒的社区、生态系统和许多工具,它包装的语言很好地解决了我们很少有人遇到的问题。虽然表面看起来非常出色,但实际编写代码的时候,你才能真实地体会。
由于Rust提供了非常全面的错误消息和文档,我们很容易忘记它实际上是一种非常底层的语言。我们被社区和种种工具所吸引,以至于忘记了底层的语言实际上很糟糕。也许Rust远非大多数底层语言可比,但请记住垃圾收集器很棒。在使用GC的时候,我们无需处理任何可能会导致Rust出现问题的工作。也许这会降低性能,但是对我来说,能够快速编写代码的能力远胜于额外的性能。
评论1:
我不太理解文中有关异步的讨论。由于Rust对于线程、Sync、Send和async接口函数的要求,导致异步编程非常困难,但我感觉他们是在没有理解需求的情况下试图将代码改成异步。实际上根本没有必要。你也可以使用传统的回调函数方式使用异步API,不需要使用Rust的异步机制,你也可以使用线程。如果你不喜欢Rust的异步(或者不会用),那就不需要用。
诚然,现在Rust的async有许多不招人喜欢的地方(许多问题已经在解决中),但直接用线程不就好了?
读完之后我认为切换到F#(或OCaml)是一个正确的选择,因为这样可以得到语义相近的好处。但批评Rust的一些论点实在不敢苟同。似乎就是在说,不用Rust是因为Rust没有好用的GCP库,而他们不想自己写垃圾回收,但仅此一点貌似篇幅不够,所以加了许多别的东西。
评论2:
我认为作者遇到的许多问题都是因为他想用Rust来写F#或OCaml的代码。尽管Rust建议你将应用程序按照“全局函数式”的方式组织(例如,避免使用共享可变状态),但如果你想使用小范围的函数式概念:递归、高阶函数等,那将是一场灾难。
而最终他遇到的异步递归或pinning的问题有一半是由于他不够专业,因为我写了将近一年的Rust异步,从来没遇到过类似的问题。
原文:https://blog.darklang.com/why-dark-didnt-choose-rust/
本文为 CSDN 翻译,转载请注明来源出处。
更多精彩推荐
☞faker.js 登 GitHub 趋势榜标星 27.1k,可大批量生成假数据!
☞太扎心!人艰不拆!16 个程序员专属笑话讲给你听
☞中国联通最快明年实现2G全面退网;苹果发布iOS 14.3后火速撤回:原因未知;Angular 11.0.0 正式发布|极客头条
☞强化学习:10种真实的奖励与惩罚应用
☞打钱!我的数据库被黑客勒索了!
☞对区块链撒谎:将“垃圾进,垃圾出”问题应用在去中心化网络上