畅谈百年编程语言

某些软件开发者,或更普遍的是生意人,喜欢谈论百年编程语言,甚至是百年框架。

这个话题非常大胆。我是说,软件开发发展到今天,差不多已经有 65 年了。而框架就更年轻了。断定你的语言或框架能活到一百年,这是一个相当大的论断。

你可以看看保罗·格雷厄姆(Paul Graham,美国程序员、风险投资家、博客作者和技术作家。他以 Lisp 方面的工作而知名)关于百年编程语言的论断。他的意思稍有不同:他所指的是一种语言,其后代将在 100 年后以或多或少可辨认的形式与我们同在。比起我,他更关注的是编程范例和特性。但是如果 C 接替了 Algol,他认为这没问题,他只是想知道 Algol 的哪些特性足够好,能够在转变中存活下来。

我想知道 100 年以后,哪些语言还会存在,并且基本上还可以使用。

人们流行这样的说法:“一种语言要想在一百年后仍然可用,它需要有良好的性能。”你将如何评估这样的说法?你要怎么开始呢?

这并不是反问。让我们开始评估吧。

最古老的语言能告诉我们什么?

如果我们最古老的语言有 65 年的历史,那么就没有百年编程语言的例子。不过,我们有一些 60 多年的编程语言。我们可以从最古老的例子中看出什么?

一种语言已经普及,就很难消亡,但是往往会产生变异。Fortran 的 2008 版并不完全像 Fortran77 或最初的 Fortran(1957 年)。但是感性链是非常连续的。这里面有许多共同点,这是可以辨认的。它有一个持续的编程社区。Fortran 在科学和数学界一直很受欢迎,直到今天也是。例如,Fortran 仍然是超级计算机编程的主要语言,在这种情况下,你为高性能付出了太多,你需要一种尽可能快的语言。比如说,Fortran 明显比 C 快得多。这种需求和开发者社区一直在推动着 Fortran 的发展。

这就很有意思了:我们说一种百年编程语言时,并非指它的语法和特性的延续。我们要看的是一个持续的编程社区。Perl 是个有意思的例子。Perl 第 6 版(现在叫 Raku)旨在大幅改动这门语言,并且确实做到了,但花了很多年。Perl 5 就这样被分裂成了一个单独的社区,Perl 6 则作为一种新语言持续发展。如果 Perl 6 很快就会完成大规模的重写,那么我们一定会将其称为 Perl 社区。Perl 1 和 Perl 2 看上去和 Perl 5 很不一样,没有人会争辩说我们不应该把 Perl 1 和 Perl 5 称为同一种语言。与 Perl 6 不同,它有一个相当连续的编程社区。用户(软件开发者)的分裂使得人们认为 Perl 6 实际上是一种不同的语言。

LISP 是另一种古老的语言,它有很多很多的后代,如 Guile、Scheme、Clojure 和 Racket。它们从来都不是广受欢迎的语言,但从整体上看,它们并没有消亡的征兆。LISP 虽然很多小方言都已不复存在,但仍未消亡。较大的方言(如 CommonLISP)仍然保持着增长的势头,也没有真正消亡。所以:我们并不总是指单一语言的编程社区。你也许可以争辩说,例如,即使 Clojure 变得巨大,LISP 仍然是消亡的。但是,大多数人在谈论 LISP 时,并不是指非常具体的原始 LISP。就像 Perl 1,它的后代已经发生了巨大的变化,但它们仍然是非常容易识别的、同样的基本语言。更重要的是,如果你了解 LISP 的老方言,那么要掌握一种 LISP 的新方言就不会太难了。它们之间有很多共同点,可以让它们快速、顺畅地共享一个更大的开发者社区。

语言是如何消亡的?

“消亡”是什么?大多数情况下,我的意思就是“消亡”,正如拉丁语的消亡。有一些小而孤立的讲拉丁语的学术和宗教团体。但是,对于大多数人来说,这并不是一种普通的日常语言。

维基百科关于编程语言历史的页面,如果你还没有看过,那就值得一看。

Algol(1958 年)已消亡。它有后代,但它们看起来不太像 Algol。所以:这就是一种语言消亡的一种方式。它完全可以被更好的后代吞噬,它们带走了它的整个用户群。“Algol 家族”中包含了远亲,如 Perl,以及使用较少的 Delphi 这样的分支。但它们也包括 C、C++、Visual BASIC 和 Java。这些都是非常流行的语言,早已吞噬了 Algol 的整个开发者社区。尤其是 C,它的诞生很早,也很受欢迎。这就意味着没有什么理由继续使用 Algol。

有些语言从未真正确立。FLOW-MATIC 是格蕾丝・赫柏(Grace Hopper,1906 年 12 月 9 日~1992 年 1 月 1 日,美国海军准将及计算机科学家,世界最早一批的程序员之一,也是最早的女性程序员之一)编写 COBOL 之前的第一种语言。它影响了 COBOL,但它本身从未被广泛使用过。许多如今已消亡的语言都是如此:用户很少,社区也不大。

如果你愿意,你可以包括很多“原始语言”。我指的是那些大多变异成其他语言的语言。FLOW-MATIC 变成了 COBOL,所以它的小用户群变成了 COBOL 用户。这就是很多语言的消亡方式:它们加入了另一种语言,它们的社区变成了那个语言的社区。

“先驱者”和原始语言不必由同一批人设计。FACT(1959 年)现在被认为是 COBOL 的先驱,因为它影响了设计,它的社区变成了 COBOL 程序员。但那不是格蕾丝·赫柏的项目。不同的人,但是社区变成了 COBOL 程序员。所以这也不是谁编写了这种语言的问题。这是关于用户社区的去向。

同样,C 也是以 BCPL 命名的。BCPL 用户(没有那么多)变成了 C 用户。但是 BCPL 是马丁・理察德(Martin Richards,1940 年 7 月 21 日 ~,计算机科学家,为 BCPL 编程语言的发明者,发明了 TRIPOS 操作系统)写的,而不是 C 的作者之一。这是关于用户社区,而不是语言作者或特性。

消亡意味着什么?

在我们深入讨论之前,我想先谈谈“消亡”一词在编程语言中的一个明显的、有点愚蠢的用法。

编程语言是由人类编写的,是给人类的。它们既是人类的语言,也是人类的文化。它们恰好也能开发出实用的计算机程序。它们和其他人类语言或文化一样,也容易受到趋势的影响。

当你听到有人说“Rails 已经消亡”时,你可以肯定他们并不是指“没有程序还在运行 Rails”或“没有公司还在使用 Rails”或“没有新项目用 Rails 编写”。这一切都很明显,很清楚,根本不真实。

他们指的是“Rails 现在不再是‘’了,你应该学习其他东西。”这就意味着 Rails 的使用机会比其他语言、框架或技术要少。这也可能意味着,初创公司的创始人对其他事物的青睐程度要高得多。不管怎么说,这并不表示 Rails 不被使用或不能使用。他们的意思是它不再是“”。

对于我们现在所讨论的一切,我们可以安全地忽略这种用法。的确如此。任何超过 25 年历史的语言都不再是的新语言,也不会被大肆宣扬。根据这种定义,对于一种具有百年历史的编程语言,其百分之百的绝对要求就是,它已经消亡。

是什么让语言变得孱弱?

语言不会一下子就消亡。随着最后几个日常使用该语言的用户相继去世,或者发现其他的日常语言时,它们就逐渐消亡了。

它们日渐孱弱,直到基本上消亡,最后彻底消亡。

是什么让语言变得孱弱?

一件事就是社区分裂。在分裂之后,Perl 5 和 Raku 都要弱得多。Python 从版本 2 到版本 3 的过渡非常艰难,也让它失去了市场份额。Ruby 从 1.8 到 1.9 的过渡也类似,如果不是那么迟缓和戏剧化的话。当你做一些分裂社区的事情时,那么你的社区就会变得孱弱。在像 Perl 这样的极端情况下,它的社区已经缩小到足以消亡的地步。

这也是语言倾向于被自己的后代杀死的原因之一。既然有了 C 语言,为什么还要继续使用 Algol?如果 FLOW-MATIC 的作者已经转而制作 COBOL,为什么还要继续使用 FLOW-MATIC 呢?同一种语言的后代往往对该语言的社区很有吸引力。

更重要的是,语言社区倾向于离开,转而选择其他解决他们同样问题的工具。开发人员从 Perl 转向 Ruby 或 Python 语言,这些语言以类似的方式解决类似的问题。Python 和 R 之间在统计学方面的关系一直很紧张,这是因为它们都为统计学家解决了有用的问题。并不是很多人为了语言本身而采用它。他们有需要解决的问题,而语言可以解决这些问题。

这并不只是一个新的竞争者出现时的问题。当一个旧的解决方案不再有效时,这也是一个问题。与 JBoss 等旧的 Java 框架相比,Ruby 和 Rails 曾被誉为一个非常简单的 Web 编程栈。但较新版本的 Rails 要求在面对安全威胁时不断加固框架,这就增加了部署的难度。Heroku 不再提供免费计划,也没有一个明显的 Heroku 替代品。因此,Rails 目前的部署比以往任何时候都要糟糕。Rails 在解决特定用户问题上的能力的确有所下降。这样就会削弱这个框架,也削弱了得益于 Rails 用户社区的 Ruby。

如果语言不再像以前那样很好地解决问题,或者当有一个更好的竞争者来解决问题时,这种语言就会变得孱弱。

是什么让语言变得更强?

如果一种语言必须为用户解决问题,那就表明这个问题很重要。

小众环境强化了一种语言。R 语言非常适合统计,并且在社区中有很大优势。大家都认为,你不会用它来写操作系统。

Java 是最近流行的通用语言。之后的一切都成了这样或那样的小众语言。Python 擅长数学、科学和人工智能编程,Ruby 则擅长于动态 Web 应用。JavaScript 是浏览器内编程和一些相关的服务器端的主要拥有者。Fortran,曾经是通用的,现在在超级计算和某些高度数学化的应用中继续存在。C 语言在操作系统和驱动程序中退居一席之地,因此它现在被从一般应用程序编程中驱逐出去。

小众的力量是强大的。

我不会说“Java 是终极的通用语言,永远都是。”基于 65 年的历史,这样的声明似乎过于强烈了。Java 27 年的运行并没有告诉我们,将不会有其他流行的通用语言。它只是告诉我们,它们将相当罕见。

这就说得通了。小众非常强大,要想成为真正的通用语言,就得避开它们。甚至 Java 在使用时也存在着一些重要的限制,例如,高内存利用率使得其不适合小型嵌入式处理器。或许“通用”这一描述即将消亡,被众多的小众语言所吞噬。

也可能不是这样。这一切都是近期发生的历史,因此说它是永久的就太愚蠢了。我们现在还不清楚。

不过,小众意味着该语言有重点和目的。小众语言之所以强大,是因为它能让用户社区知道在帮助谁,以及如何帮助他们。这也是围绕书籍、产品或许多其他事物的社区所需要的。

编程语言具有相同的要求是有道理的。

那么,对于一门百年语言来说,性能是必要的吗?

我说过,我们会评估性能是否是百年语言的要求。

让我们来评估一下。

Fortran 是最古老、最繁荣的语言之一,它的生死取决于性能。所以这是“是”栏中的复选标记。

LISP 是另外一种最古老的语言,它并不注重性能,但是由于其灵活性和易于实现而繁荣。所以,在“否”栏中有一个复选标记。

但这当然不是投票。相反,Fortran 和它的用户社区所关心的是性能。LISP 的重点是灵活性和可表达性。

性能是必要的吗?那得看情况了。这就是这种语言的意义所在吗?这就是它的关注点吗?

性能并不是一件坏事。但如果你向 Fortran 社区询问,“你需要编译器实现更简单吗?”他们会说“不关心”。LISP 社区可能不会说他们不关心性能,但他们也不会回避低性能的有趣解释器。问题不在于“高性能好吗?”而在于“它在你的优先级列表中排名第几?”

BASH,命令行 shell,性能相当差,并且一直如此。这不是它的卖点。相反,它的社区想要的是兼容性、稳定性和易用性,并希望它能随时随地地摆脱困境。如果你做了一个高性能的 bash 实现,那么只有几个人会使用它。至少,他们会使用它,除非它损害了其他目标之一。所以,我们假设的高性能 BASH 可能已经成为泡影,因为“普遍可用”和“100% 兼容”对其社区来说是如此重要。

优先级不能改变吗?

你可以争辩说,仅仅因为某些东西对早期用户来说不是优先考虑的,并不意味着它现在就不是优先考虑的。也许 Ruby 或 Python 的第一个版本可能很慢,但现在的一些用户或许更关心性能,而非可表达性。PHP 的初衷或许是为了方便部署,但它目前的 Laravel 用户可能想要一个更干净、更有表达性的核心语言,并愿意为此牺牲一些兼容性和可用性?

这也不是没有可能。

问题在于你的社区的延续性。很难赶走一个社区然后吸引另一个社区。 关于你的太多旧信息,现在都不正确。不好的信息会吸引你不想要的人,也会排斥想要你当前关注的人。因此,在一门语言中,修改你所能提供的东西可能是最危险的行为之一。这就是我们之前讨论过的社区分裂的根源。

你可以做一些小的改变。额外的一点性能不会使任何人离开。但是有时你得衡量一下其中的优劣。

Ruby 已经开始被更多的大公司使用。总的来说,这是一件好事。但这也是一个拐点,一个我们的权衡改变的地方。我们是否要减少可表达性,因为无限制的可表达性会给更大的团队带来麻烦?也许吧。如果这种改变是有效的,它可以增加 Ruby 开发者社区的规模和寿命。但是,像这样的改变是语言面临的最大的消亡风险之一。

顺便说一下,这也是像 YJIT 和 TruffleRuby 这样的 Ruby 优化项目大多不推动限制 Ruby 可以做什么的原因之一。额外的性能不错,但可表达性是 Ruby 在早期获胜的关键。如果性能不影响可表达性,那就很好。并非每个地方都如此。但对于 Ruby 这样的小众语言来说,却是如此。

更快,更慢

对优先级的担忧也是为什么 Python 在 Python 2 向 Python 3 的过渡中花费如此漫长而痛苦的时间。Python 在向后兼容方面做了非常缓慢、慎重的改变。在极少数情况下,如果它破坏了向后兼容性,就会被认为是对用户社区的一种背叛。

Ruby 的情况就好得多,因为 Ruby 并没有承诺太多的向后兼容性。Ruby 的承诺更像是,“我们保持了相当多的向后兼容性,但当我们想让语言变得更好时,有时会出现一些问题,你只需要处理这些问题。”Python 赢得了数学 / 科学社区,需要程序在 20 年后继续运行;Ruby 则赢得了 Web 编程社区,不管怎样,那里的标准每 5 年改变一次。这绝非偶然。

另外,这并不意味着“Ruby 是对的,Python 是错的”,也不意味着相反。这并不是说“更适合 Web”就是好的,“更适合数学和科学”就是不好的。这是用另一种方式来说明小众有多强大:如果你可以在一件事上做得好,在另一件事上做得不好,你就可以在这一件事上做到极致,并击败在这两件事上都不出色的通用语言。

赢得 Web 的小众语言得益于快速的变化,比如 Ruby。赢得数学 / 科学的小众语言得益于其缓慢的变化,如 Python。

一门语言能够如此优秀,以至于能够战胜两种语言,也不是不可能的。但是,它最终还是要和快速变化和缓慢变化的后代进行竞争,因此,你会认为很难弥合这一差距。

顺便说一下,Perl 也是如此。很久以前,Perl 是唯一的脚本语言。它仍然非常适用于总结大量文本文件。但是现在它正在与 Ruby(一个快速变化的后代)和 Python(一个缓慢变化的后代)进行竞争。Ruby 接管了 Perl 注定要失掉的 Web 小众社区。

这并不限于脚本语言。由于各种原因,C++ 的变化比 C 快得多。C 受益于某些领域的缓慢变化。设备驱动程序编写者多久更改一次语言?他们喜欢稳定性。C++ 受益于其他领域的快速变化,如应用程序编程。从长远来看,这并不是 C 和 C++ 之间唯一的区别。但这是一个重要的问题。

对事实置若罔闻

这里有一种我们还没怎么谈过的语言:COBOL。COBOL 程序员不多,而且他们几乎完全是在维护旧的代码。然而,数以百万计的 COBOL 代码行保持着大量的银行基础设施的运行。它已经存在了几十年,几乎没有变化。在那些摆脱了 COBOL 的地方,他们通常通过机械地将 COBOL 翻译成另一种语言(基本上总是 Java)来实现。

就运行的代码行数而言,COBOL 具有极大的活力和生命力。如果明天所有的 COBOL 代码都蒸发了,整个国际银行系统就会立即崩溃。

对于将 COBOL 用于新项目的人来说,COBOL 几乎已经消亡了。编写的新 COBOL 项目非常非常少。

所以,它是生存的还是消亡的呢?大部分都消亡了。

现在没有一个大型的 COBOL 开发者社区。人们正在逐渐摆脱 COBOL。COBOL 就是如果你从不改变你的权衡,并且最终你的用户社区不关心你所提供的内容,那么将会发生的情况。改变就是冒着消亡的风险,要么是一点点,要么是很多。永不改变,终将消亡。

不就是因为 COBOL 老了吗?不是。COBOL 比 Fortran 略微年轻,而 Fortran 在它的小众社区中出奇地健康和充满活力。

最主要的是,这提醒我们,“这种语言不能消失,它被某公司使用”只能让你走到这里。C++ 在谷歌中得到了广泛的应用,但是这并不能成为其生存的唯一原因。Shopify 使用 Ruby,但是它的寿命只有这么长。

你需要新的用户,新的承诺,新的血液。

承诺是如何实现的?

C 的旧承诺之一是像 PDP-11 计算机一样工作。虽然现在依然如此,但是对每个人来说,这已经不是最重要的事情了。说来也怪,早期的 LISP 也做了类似的事情,这就是为什么“列表头”/“列表尾”仍然被命名为“car”/“cdr”,以古老的 IBM 704 上的机器寄存器命名。

这些都是古老的语言,这些特性可以被认为是古老的承诺。

LISP 最初需要一点性能来使其数学表达能力可行。最终,处理器变得更快,这一点被放弃了——在现代 LISP 的实现中,car 和 cdr 绝对不是简单的寄存器访问,而且没有人在乎。只要性能可以接受,这对他们的社区来说并不是一个重要的承诺。而“可接受”在当时是相当宽松的。例如,CommonLISP 比 C 语言慢得多,但大多数情况下,这没什么问题。

你可能会认为,如果同样的变化,C 会比较困难。如果 C 承诺像处理器一样,那么当处理器发生变化时,它是怎么做的呢?较新的处理器使用 SIMD 指令,如英特尔 SSE 指令。这些指令进行大型阵列操作,而这是快速执行大型任务的核心。C 语言从未真正为它们添加任何类型的抽象。C 语言看起来仍然很像 PDP-11,它没有这种东西。

但是我们经常不明白哪些承诺对我们的开发者社区是重要的。C 不需要成为最快的语言。否则像指针别名这样的问题就会把它的早期用户赶到 Fortran 的怀抱中,而 Fortran 是一种更快的语言,没有这个问题。

C 是一种足够快、足够令人愉悦的语言,它能够很好地兼顾特性和性能。老实说,在其最鼎盛的时候,没有多少竞争者,因此,它无需为自己的承诺和小众而担忧。现代 C 语言在其现代小众领域(操作系统、设备驱动、低级系统编程)中更多的是关于控制而不是性能。它的性能必须是可以接受的,但它主要是关于精确的逐位布局。如果它能减少几个 CPU 周期,就会有更多的 CPU 周期可供使用。因此,指针别名不会导致用 Fortran 编写设备驱动程序。

承诺确实会随时间而改变。它们必须如此。这不是一个避免所有改变的问题。这是一个管理问题。

承诺会改变多少?C 语言诞生于 1972 年,距今 50 年。这些年来,它所经历的所有变化,使它在成为一个百年语言的过程中走过了一半。它还很健康,很有活力。我想它会成功的。

那么,你如何坚持 100 年?

如果你希望你的语言能持续 100 年呢?如果你在一个你喜欢的语言社区,或者你是一个语言设计师呢?你会怎么做才能设计出一种百年的语言,成为时代的纪念碑?

你不能只关注语言特性和句法。英语不断吸收新的词汇,这既不是它最大的优势,也不是它最大的弱点。重要的、持续的部分是说话者的社区。我们只关心这个社区的词汇。

Java 或 Fortran 或 Ruby 或任何你喜欢的语言也是如此。

为了保持一种语言的健康发展,你需要知道你对社区的承诺是什么。为什么会有这些承诺?这就是必须保持真实的东西。这个承诺的某些部分是复杂的:一个特定的新特性究竟是好是坏?承诺的某些部分是微不足道的,因为有时你与你的听众在这里的核心原因发生冲突。在 Fortran 中,他们不把可表达性看得比速度更重要。而在 Ruby 中,他们很重视。在 Rust 中,内存安全是最重要的。在 C 语言中,能够以奇怪的方式处理内存,远比安全更重要得多。

这些优先级列表都没有错。它们定义了小众语言。

这也意味着你需要小心“跳出你的小众”。你的小众就是你的优势。小心翼翼地离开它,而且有点胆怯。种种迹象表明,语言在将来会变得越来越小众,而非越来越少。

这也意味着你遵循亨利・福特(Henry Ford,美国汽车工程师与企业家,福特汽车公司的建立者。亨利・福特是世界上第一位将装配线概念实际应用在工厂并大量生产而获得巨大成功者。亨利・福特不是汽车或是装配线的发明者,但他让汽车在美国真正普及化。这种新的生产方式使汽车成为一种大众产品,它不但革命了工业生产方式,而且对现代社会和美国文化起了巨大的影响)的各种著名建议时必须小心。“如果我问他们想要什么,他们会说要一匹更快的马。”“只要是黑色的,他们想要什么颜色都可以。”有时你可以高瞻远瞩,给你的社区一些他们没有想到的要求。但是,如果他们说他们不想要什么,请记住你处于危险的境地。对于世界上的每一个亨利·福特来说,有太多的人不是亨利·福特,而且他们都猜错了。

这里重要的部分是要问,“我们的承诺是什么?”想一想这些承诺有多久。100 年后人们还需要你所提供的东西吗?100 年前他们需要什么?

我并不是说这些都很容易。但重要的是,要意识到 100 年有多么漫长。

作者简介:

诺亚·吉布斯(Noah Gibbs),教授各种编程技巧。平时会参会发言,写书,举办研讨会。曾为硅谷的初创公司工作。

原文链接:

https://codefol.io/posts/the-hundred-year-programming-language/

本文文字及图片出自 InfoQ

余下全文(1/3)
分享这篇文章:

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注