前几天,我读了这篇“20种有史以来最重要的编程语言”,这是一张“我刚刚编出来的荒谬的表格”。它之所以荒谬,是因为他列出的“最重要的”语言中包含了 Go,但没有包含 ALGOL、Smalltalk 或 ML。他也没有提到 Pascal,因为它“基本上已经消亡了”。荒谬!这完全违背了“有史以来最重要”的含义。
那么,让我们来讨论一下那些“几乎已经消亡”的语言,以及它们如此重要的原因。
免责声明:是的,不是所有这些都已经消亡了,也不是所有这些都被遗忘了。就像大多数人一样,是听说过 Smalltalk 的,对吧?此外,这可能还会出现上亿个错误,因为当你对 60 年的计算机历史进行调查时,你总会犯一些错误。如果你发现什么错误,可随时大声指责我!
免责声明 2:是的,我知道其中一些是“首个发明”的,而另一些是“首个普及”的。历史很复杂!
探测影响力
在开始之前,先简单介绍一下如何寻找影响力。仅仅知道 X 是首个具有 Z 特性的语言并不意味着 X 实际上影响了 Z。虽然 Absys 可以说是首个逻辑编程语言,但几乎所有的逻辑编程实际上都是源于 Prolog 了,后者是独立开发的。最终,只有一种方法可以确定 X 影响了 Y:引用。这意味着:
Y 在其参考手册中引用了 X;
Y 引用了的论文中引用了 X;
Y 的作者说过“我们受到了 X 的影响”。
引用是可传递的。有时,Q 语言的手册会列出激励性文献 R,其中 R 引用了论文 S 作为灵感,并提到 S 的灵感是从语言 T 那里得到的。那么,我们就知道 T 影响了 Q,即使这个链条有好几个步骤。这意味着需要通过多种途径寻找信源。为了加快速度,我们使用启发式的方法来决定在哪里查找。
一种有效的启发式方法是编程语言的同根词。对于语言来说,独立地提出相同的语法是非常罕见的。因此,如果两种语言某种语法相同,则其中一种可能会影响另一种。例如:即使没有阅读 Matz 的设计决策,我们也知道 Ruby 受到了 Smalltalk 的影响,因为它们都使用 select 方法过滤列表。这不是确凿的证据。也许它是 Matz 独立开发出来的,也许 Ruby 和 Smalltalk 都受到共同祖先的影响。但这给了我们一个开始寻找的方向。
语言
COBOL
背景:CODASYL,1960 年。COBOL 是由计算领域的商业/科学分裂形成的。那时,高级工业语言要么用于工程计算,要么用于管理数据。工程师们都支持 FORTRAN,而商业世界却是一团乱码,充斥着诸如 COMTRAN、FLOW-MATIC 等语言,因此,国防部成立了一个委员会,共同制定了一种通用的商业语言。那就是 COBOL。
COBOL 与 ALGOL、FORTRAN 和 LISP 一起构成了四种“母”语。今天,虽然我们认为它是小语种,但它曾经是世界上最流行的语言。我们的许多遗留商业系统仍然在其上运行着。
重要意义:就语法和语义而言,我们在现代计算中很少看到 COBOL 了。 COBOL 最重要的附加功能是提出了记录数据的概念。在 FORTRAN 和 ALGOL 中,唯一的数据结构是静态数组。但是,在 COBOL 中,我们可以读取包含分层数据的结构化文件,它会自动将这些文件解构为代表变量。它是现代结构体的先驱。
消亡原因:这里有两个因素。一:COBOL 与其他 PLT 所做的工作没有重叠。很少有人会基于 COBOL 进行构建。这意味着,建立在祖先教训之上的第二代或第三代语言几乎没有 COBOL 基因了。这不是 COBOL 的本质问题,更多的是因为学术界对 COBOL 的创建过程不屑一顾。CODASYL 是一个商业团体,显然它不值得关注(1)。即使是对于今天的语言来说,COBOL 也是非常复杂的。这意味着 COBOL 编译器在微型计算机和微型电脑上落后于同时代的编译器,为其他语言的繁荣并最终超越它提供了空间。
ALGOL
背景:ALGOL 委员会,1960 年。ALGOL-58 早在两年前就问世了,但很快就被取代了,因此我将它们组装在一起。该委员会想为算法研究提供一种良好的语言。换句话说,ALGOL 是一种形式化的“伪代码”。
在四种母语中,ALGOL 是最早“消亡”的语言。大家仍然知道 LISP(2) ,COBOL 仍然为大量的遗留系统提供支持,并且大多数科学软件包仍然具有 FORTRAN。但是我见过很多程序员,他们甚至都没有听说过 ALGOL。你可能会认为它是最不重要的母语了,但事实恰恰相反。在这四种母语中,只有 LISP 可以与 ALGOL 的普遍重要性相提并论。
重要意义:让我们来看一下:词法作用域、结构化编程、嵌套函数、形式化语言规范、按名称调用语义、BNF 语法、块注释……今天的每一种现代语言都深受 ALGOL 的影响。
消亡原因:ALGOL 是一种研究语言,而不是商业语言。它是专为算法研究而设计的。规范没有定义任何 I/O,这使得它在实践中无法使用。当然,你可以编写一个编译器扩展,但是你还需要添加更多其他的东西。
人们就是这么做的。 1960 年,有 70 人通过用 I/O 和额外的数据结构来扩展 ALGOL,开发了大量的类似 ALGOL 的语言。这包括 JOVIAL、SIMULA、CLU 和 CPL。后来的语言都是基于这些类 ALGOL 语言而不是直接基于 ALGOL 进行扩展的。我们称 C 为“类 ALGOL(ALGOL-like)”,但实际上它是“类 BCPL(BCPL-like)”,也就是“类 CPL(CPL-like)“,即为类 ALGOL。 ALGOL 的孩子们把它埋没了。
最终,ALGOL 人试图将其扩展到 ALGOL-68,而 ALGOL-68 完全脱离了 ALGOL-60,但它并没有获得那么大的影响力。 ALGOL-60 的血统通过 Nikolaus Wirth 的 Pascal 仍在延续。
APL
背景:Ken Iverson,1962 年。最初它是一种用于数组数学的手写表示法,后来 IBM 将其作为编程语言使用。作为一种语言,APL 专注于数组处理:它能够精确地处理大数字块。
如果你以前曾听说过 APL,则可能知道它是“那种奇怪的符号语言”。最臭名昭著的代码片段之一就是这个“生命游戏(the Game of Life)”的实现:
必须使用专用的键盘来编写它,就像这样:
APL 键盘(来源)
尽管如此,APL 因其内存需求低而在大型机上广受欢迎。
重要意义:数组处理。每次将两个数字列表相加就意味着需要一个映射或一个循环,APL 引入了同时操作整个数组的概念。例如:
这在科学界确实是一件大事。如此多的应用数学都可归结为对大型矩阵的大规模运算。当你可以把外部产品 ∘.f ,外部产品就很容易拿到了!
通过这一创新,APL 引出了 R、numpy、pandas、Matlab 等。APL 的直系后代还包括:J、Dyalog、K、Q。它们虽然没有那么成功,但在金融领域仍然有大量的应用。
消亡原因:很明显,问题在于键盘。如果你无法使用 ASCII 进行编写,那么你就不能编写太多的内容。Iverson 用 J 修复了该问题,J 使用了有向图来代替不同的符号。编写~:,而不是≠。不过,那是在 1990 年,要普及一种完全不同的编程风格还是为时已晚了。
更微妙的问题在于,APL 和 J 仅适用于同构数据的处理。不能将字符串和数字都存储在同一个数据结构中(除非你使用 box,这是一个完整的“蠕虫罐头”),并且处理字符串通常是一场噩梦。因此没有数据帧,这就将许多现代数据科学排除在外了。
扩展阅读:作为思想工具的符号。
BASIC
背景:John Kemeny,1964 年。最初它是一种简化了的类 FORTRAN 语言,旨在帮助工程技术以外的人们使用计算机。
BASIC 的真正腾飞是在微型计算机时代。最初的微型计算机没有足够的内存来编译“真正的”编程语言,而我们可以把 BASIC 编译器精简到大约 2 KB。 BASIC 成为了早期程序员的通用语言。在 20 世纪 70 年代,如果你在家编程,那么你可能是在微型计算机上编写 BASIC。
重要意义:其最大的技术影响力在于运行时解释器。 BASIC 是首个具有实时解释器(the Dartmouth Time Sharing System,达特茅斯时间共享系统)的语言,领先了 APL 一年。而且 APL 系统仅面向 IBM 客户,因此,在很长一段时间内,实时解释器就是 BASIC 的,或是不存在的。(3)
BASIC 有更大的社会影响力。它为家庭,尤其是孩子们带来了编程。 在 80 年代和 90 年代,许多有影响力的程序员首先学习的都是如何使用 BASIC 编程。许多企业程序也是用 BASIC 编写的,这可能加速了 Cobol 的衰落。
BASIC 还有一个妙招:Office 工具!微软最终将 BASIC 变成了 Visual Basic,并将其用作 Office 的宏语言。之后,将它扩展到了 OpenOffice 和 LibreOffice,从而巩固了 BASIC 在特定利基市场的地位。最近,它已被 JavaScript 取代,现在成为了一种遗留的宏语言。
消亡原因:人们认为 BASIC 是一种“次要”的语言。如果你是个小孩或小企业主,你可能会使用它,但是真正的程序员使用的是真正的语言。一旦制造商可以廉价地制造出具有超过 16k 内存的微型计算机时,他们就开始会为了 Pascal 和 C 而贬低 BASIC 了。
BASIC 作为一种遗留的语言教学方式在孩子们的生活中延续了一段时间,但似乎也已经消失在这个利基市场之外了。
PL/I
**背景:IBM,1966 年。IBM 的业务被分成两种语言:科学家使用 FORTRAN,商业人士使用 COMTRAN。面对来自 COBOL 的竞争,为了简化系统,他们试图开发一种对工程和商业都有用的语言。它看起来像是两种语言的超集,在顶部还添加了许多附加功能。(4)**现在每个人都可以使用相同的语言了,并且 IBM 可以赚很多钱!耶!
重要意义:ALGOL-68 的作者嘲笑 PL/I,将其称为过时的语言。但是 ALGOL-68 所做的每件事情,PL/I 都能做得更快更好。虽然 COBOL 是首个提出结构化数据的,但 PL/I 是首个将其作为类型实现的语言。在 COBOL 中,使用名称读取用户会用到两个全局变量:user 和 name。在 PL/I 中,可以使用一个带有 user.name 字段的变量。 PL/I 还是首个使用了指针操作直接内存、使用了常量和函数重载的高级语言。(5)
这些概念中有许多是通过 C 进入主流编程的,C 是 BCPL 和 PL/I 的结合体。 C 甚至使用了 PL/I 的注释语法。
消亡原因:所有的 FORTRAN 程序员都认为它太像 COBOL 了,而所有的 COBOL 程序员都认为它太像 FORTRAN 了。 IBM 曾试图用一种语言来处理这两种既定的语言,但这种语言要复杂得多。他们是唯一使用编译器的团队,但这也无济于事,这意味着其他所有人都不信任厂商锁定。当 IBM 能够在这两个问题上取得进展时,更广阔的计算世界已经进入到了微型计算机时代,在那里 PL/I 被 BASIC 淘汰了。
扩展阅读:PL/I的选择。
SIMULA 67
背景:Ole Dahl 和 Kristen Nygaard,1967 年。他们扩展了 ALGOL 来进行仿真。首先,他们开发了 SIMULA I,它具有专用的仿真器和“活动”语法。 SIMULA I 获得了一些早期的应用,但是两人对该语言的“专业化”程度以及在仿真中存在的大量重复代码感到不满。他们希望创建一个更通用的框架来表示一般事物,而不仅仅是仿真。
他们的想法是允许用户使用多态函数解析来定义称之为“类”的新类型。然后,用户可以将仿真特性作为对象系统中的一个特例来进行构建,从而用户就可以轻松根据自己的特定需求来定制对应的仿真特性了。
重要意义:虽然 SIMULA 并不是首个“真正的” OOP 语言,但它是首个具有适当对象的语言,并为其他语言的构建奠定了基础。这包括类/对象的拆分、子类、虚拟方法和受保护的属性等。 它几乎启发了所有 1967 年之后的关于对象的学术研究。CLU 和 ML 都将 SIMULA 作为其主要灵感的来源。 Bjarne Stroustroup 在 SIMULA 上完成了他的博士学位,最终将它的许多思想整合到了 C ++中。
消亡原因:在同一份博士论文中,Stroustroup 声称 SIMULA 太慢了,无法大规模使用。 “如果你不在大型机上工作,那么祝你一切顺利”。值得一提的是,Smalltalk-80 采用了同样的思路,甚至更进了一步,它在背后还附加了 13 年的摩尔定律。甚至 Smalltalk 也常常被嘲笑太慢了。每个人都在 SIMULA 中实现了他们可以集成到更快、更简单的语言中的想法。
扩展阅读:编译SIMULA:技术起源的历史研究,《SIMULA的历史》。
Pascal
背景:Niklaus Wirth,1970 年。在 ALGOL-68 的结构变得过于复杂,而不适合 Wirth 的喜好之后,他抓住了 ALGOL-60 的精髓从而开发了 Pascal。Pascal 最初是作为“ CS 入门”语言而发展起来的,到 80 年代初,它已成为了 Usenet 工作板上第二受欢迎的语言。Wirth 认为整个 Pascal、Modula、Oberon 家族是一个统一的语言概念。
重要意义:Pascal 没有引入任何全新的观点。它是一种刻意保守的语言,它试图挑选出过去十年最好的部分,并以一个统一的包来提供它们。 Pascal 将 ALGOL 语法带出了学术界,以至于 ALGOL 的赋值语法 :=被称为“Pascal 风格”。从这一点上来看,大多数看起来像 ALGOL 的语言特性很可能是受 Pascal 启发的,而不是直接受 ALGOL 本身启发的。
尽管 Pascal 并不是很有创意,但它的变体却很有创意。Wirth 还率先提出了“逐步细化”的概念,以作为编写严谨软件的一种手段。这最终导致了 Modula(推广了一级软件模块)和 Euclid(首个用于生产的形式化验证语言)的产生。
消亡原因:我在此称之为“加击”。与这个列表中的大多数其他语言不同,Pascal 没有重大的结构化障碍,也没有强有力的竞争对手。当然,它与 C 存在竞争关系,但在很长一段时间里,它仍然表现良好。人们通常将其归因于“为什么Pascal不是我最喜欢的语言”这篇论文,但这个答案太简洁了,而历史要复杂得多。另外,Delphi 在 TIOBE 和 PYPA 度量中仍然排名很高,因此它并没有像 SIMULA 一样完全消亡了。对 Pascal 陨落的准确分析比本文其余部分还要长的多。
扩展阅读:编程语言Pascal,Pascal及其继承者。
CLU
背景:Barbara Liskov,1975 年。Liskov 想要处理抽象数据类型。它就这样产生了。这就是 CLU 的全部原因。
重要意义:CLU 可能是人们从未听说过的最有影响力的语言。迭代器? CLU。抽象数据类型?CLU。泛型? CLU。异常检查? CLU。
我们并没有采用相同的术语,因此它并不是 100%都来自于 CLU,但仍然如此。未来十年的每种语言规范都是对 CLU 进行命名的。 CLU 做了很多。
消亡原因:CLU 是一种展示性语言。Liskov 想让人们接受她的想法,而不是这种特定的语言。他们做到了:如今几乎所有的语言都应归功于 CLU。她一完成 CLU,便转到了 Argus,该项目本来是为了展示她关于并发的想法。它并没有采用几乎相同的方法,而且留下了很多需要挖掘的东西。
扩展阅读:CLU的历史
ML
背景:Robin Milner,1976 年 6 月,Milner 正在构建 LCF 校准器,这是首批校准器助手之一。如果采用正确的格式编写了一份证明,LCF 可以检查出它是否正确。为了帮助撰写证明,Milner 创建了一个基于健全数学形式的元语言,这在当时意味着严格的静态类型和高阶函数。最终,ML 被标准化为 Standard ML。
重要意义:ML 可以说是最古老的“代数编程语言”。有很多东西可以归因于 ML:代数数据类型、模块、类型化函数式编程。令人惊讶的是,它并不是第一次这样做的!设计第一个 ML 只是为了配合 LCF 的使用,它并不是一种通用语言,因此缺少了许多这类特性。随着人们开始更广泛地使用它,他们从其他研究语言中汲取了一些想法并将其纳入 ML。不过,一个非常重要的概念确实源于 ML:类型推断。 ML 是首个无需键入类型的静态类型语言,因为编译器会为你找出相应类型。这为类型化 FP 逃离学术界并进入生产应用铺平了道路。
ML 还极大地影响了现代定理的校验。 Isabelle、CVC3 和 Coq 的“程序”语言都是基于 ML 的。尽管近年来,FP 的 Haskell 分支变得越来越流行,但很多类型理论都是基于 ML 的。(7)
消亡原因:ML 具有许多有趣的特性,但人们关注它仅是因为它的类型推断。当时 ML 仍然是一种专用于定理校验的语言。 SML 与 Haskell 在同一年问世,Haskell 是一种“更纯粹”的类型化 FP 语言示例。
Smalltalk
背景:Alan Kay,1972 年、1976 年和 1980 年。这有一个不断变化的目标。 Smalltalk-72 是首个,Smalltalk-76 将“面向对象编程”的概念引入到了更广阔的世界,而 Smalltalk-80 则被广泛采用。
Smalltalk 不是首个使用对象的语言,但它是首个提出“面向对象”的语言。区别在于,Simula 除了具有数字和布尔值等基本类型之外,还具有其他的对象,而在 Smalltalk 中,布尔值也是对象。如果你想了解更多,可以查看我写在这里的内容。
重要意义:我们有时认为 Smalltalk 是“真正的” OOP,而 Java 和 Python 之类的语言并不是“真正的” OOP,但事实并非如此。就像其他范式一样,OOP 是一个由许多不同影响所组成的巨大的混合体。但 Smalltalk 无疑是推广这一概念。如果你翻开 80 年代中期或 90 年代初期的任何一本关于 OOP 基础理论的书籍,它们都是建立在 Smalltalk 上的。许多人还将 Smalltalk 示例转换为 C++,少数人将使用另一种语言,但每个人都会使用 Smalltalk。
Smalltalk 还传播了对象可作为共享数据的概念,从而导致了 CORBA 的出现,并启发创建了可计算 Actor 模型。
消亡原因:人们普遍认为 Smalltalk 衰落,是因为人们改用了 C++。但这并不是真的。 Smalltalk 确实有一些问题,特别是它很难与其他工具交互,并且运行时性能很差。但是,即使到了 1990 年代,Smalltalk 仍在做着受人尊敬的生意,许多人认为它将成为一种占主导地位的商业语言。
Java 的发展趋势:
(来源)
Smalltalk 并不是“Javapocalypse”的唯一受害者:Java 还边缘化了 Eiffel、Ada95 以及 OOP 世界几乎所有的其他语言。一个有趣的问题不是“为什么 Smalltalk 会消亡”,而是“为什么 C++能够生存”。我认为这是因为 C++具有更好的 C 互操作性,因此能更容易地扩展到遗留系统中。
总结
这只是已消亡的重要语言中的一小部分。我没有涵盖 ALPHARD、ALTRAN、Argus、Automath、BCPL、COMTRAN、CPL、Eiffel、FLOW-MATIC、HOPE、Hypercard、ISWIM、JOVIAL、MacSyma、Mesa、Miranda、Multics Shell、PLANNER、SMP、Sketchpad 或 SNOBOL 。它们都以自己的方式为现代编程领域做出了贡献。历史是复杂的。
最具影响力的语言从未成为主流。很少有人会使用它们中的任何一个。但是每一种语言都鼓舞了人们,也鼓舞了其他人,因此这些被遗忘的语言的基因在它们被遗忘了几十年后才显现出来。但也有不计其数的语言没有把它们的想法表达出来。 《编程语言百科全书》列出了 8,000 多种编程语言。它们中的许多想法从未消失。想想如果没有人听说过 SIMULA,或者 Liskov 从未分享过 CLU,我们将会损失多少东西。
这就是我喜欢研究历史的原因之一。去了解我们丢失了什么并重新将其找回来。
这篇文章的初稿最初是在我的时事通讯上分享的。如果你觉得它很有趣,为什么不订阅它呢?
感谢Miikka Koskinen、Kevlin Henney、Eric Fischer 和 Levi Pearson 对本文更正和反馈。
备注
这很讽刺。
不管怎样,人们都知道 Lisplikes,足够接近了。
究竟是 BASIC 还是 JOSS 是首个尚存争议,因为它们几乎是在同一时间开发的,而且都分阶段推出的。但是 JOSS 只有几百个用户,对现代语言几乎没有影响。
请注意,PL/I 读作“Programming Language One”,而不是“Programming Language Eye”。I 应该是罗马数字。
PL/I 实际上将这些称为“泛型函数”,但其实现与重载相同。PL/I 没有任何抽象数据类型的概念,而这种抽象数据类型出现是十年之后的事情了。
这里的时间轴有点奇怪。人们说它是在 1972-73 年出版的,但他们在 1977 年时提交 POPL 论文时,声称它时在“两年前”可用的。
Haskell 从 HOPE 和 Miranda 那里获得的收益比 ML 还要多。
原文链接:
https://www.hillelwayne.com/post/influential-dead-languages/
评论