跳转到内容
← 返回先驱
编程语言先驱1924–200712 分钟阅读

约翰·巴克斯

John Backus

1953 年,IBM 的工程师约翰·巴克斯(John Backus)向管理层提交了一份提案,内容是开发一种全新的编程语言,让数学家和工程师可以用接近数学公式的方式写程序,而不必手写汇编代码。管理层的反应是怀疑的:这能行吗?翻译得够快吗? 1957 年,他带领团队发布了 FORTRAN(FORmula TRANslati…

FORTRANBNF范式函数式编程编译器

1953 年,IBM 的工程师约翰·巴克斯(John Backus)向管理层提交了一份提案,内容是开发一种全新的编程语言,让数学家和工程师可以用接近数学公式的方式写程序,而不必手写汇编代码。管理层的反应是怀疑的:这能行吗?翻译得够快吗?

1957 年,他带领团队发布了 FORTRAN(FORmula TRANslation),这是人类历史上第一个被广泛使用的高级编程语言。它不仅可行,而且在某些数值计算任务上生成的代码效率可以与手写汇编媲美。它打碎了一个长达十年的迷信:机器不可能把高级语言翻译成足够高效的机器码,程序员必须亲手写汇编。

FORTRAN 随后被用来解决天气预报、航空工程、核武器设计等大量科学计算问题,并催生了整个编译器(compiler)领域。今天,几乎所有编程语言都依赖某种形式的编译器或解释器。

破除误解:巴克斯不只是"FORTRAN 之父"

巴克斯对计算机科学有两项几乎同等重要、但性质截然不同的贡献:

一、FORTRAN 和编译器技术:实践性的,解决了真实的工程问题。

二、巴克斯-诺尔范式(BNF,Backus-Naur Form):理论性的,成为描述编程语言语法的通用符号系统,几乎所有后来的编程语言规范都用它书写。

1977 年,他的图灵奖演讲更进一步,提出了函数式编程(functional programming)范式,批判了冯·诺伊曼式命令式编程的根本性缺陷——这是一个在四十年后随着 Haskell、Erlang、Scala 等函数式语言兴起而被重新发现其价值的洞见。

现场:从混混到 IBM 研究员

巴克斯的早年并不顺遂。他 1924 年 12 月 3 日生于费城,父亲是股票经纪人,家境富裕。他在大学时成绩糟糕,先后在弗吉尼亚大学和匹兹堡大学读过书,都中途辍学。在军队里,他被测试出在医学方面有潜力,随即转去学医,但仍然无法集中注意力。

1946 年,他在纽约听了一个关于 IBM 计算机的公开演讲,被打动了。他向 IBM 工作人员提出能否参观 IBM 的计算机设备,对方不仅答应,还问他有没有兴趣来工作。他就这样进了 IBM——当时没有计算机科学学位,也没有传统工程背景,靠的是好奇心和一次参观机会。

进入 IBM 后,他展现出非凡的数学天赋,并开始研究如何简化编程工作。

FORTRAN:三年打破一个迷信

1954 年,巴克斯领导的团队开始正式研发 FORTRAN。项目从 1954 年持续到 1957 年,团队最终约有 13 人。

FORTRAN 的技术核心是编译器:一个把 FORTRAN 源代码翻译成 IBM 704 机器码的程序。当时最大的怀疑正是针对编译器:高级语言被翻译成机器码,生成的代码真的会比手写的汇编高效吗?

巴克斯团队的答案是肯定的——原因在于他们在编译器里实现了大量的优化技术: - 公共子表达式消除:相同的计算只做一次 - 循环不变量外提:把循环内不随迭代改变的计算移到循环外 - 寄存器分配:最大化利用处理器的快速寄存器

这些优化技术后来成为了编译器理论的基础,被系统化研究至今(其中很多技术在弗朗西丝·艾伦 Frances Allen 的工作中被进一步理论化)。

1957 年 4 月,FORTRAN 发布。工程师们试用后发现,大多数情况下 FORTRAN 生成的代码只比手写汇编慢 20% 以内,在某些情况下反而更快(因为编译器比人更一致地应用了优化)。FORTRAN 迅速传播,很快成为科学计算的主流语言,在数值计算领域使用了七十年,至今仍被气候模型、量子化学和高性能计算广泛使用。

第一个大型软件工程项目

回看这段历史,FORTRAN 项目还有另一个常被忽略的身份:它是人类最早的大型软件项目之一,也因此最早踩中了大型软件项目的所有坑。

1954 年 11 月,巴克斯和三位同事拿出了 FORTRAN 的初步外部规范。团队当时对语言设计本身的看法近乎轻率——巴克斯多年后回忆:"我们只是边做边把语言造出来。我们不认为语言设计是个难题,它不过是真正问题的前奏:设计一个能产出高效程序的编译器。"真正的工作量在编译器上,而编译器的工作量被严重低估:整个项目最终耗费约 18 个人年,编译器本体达数万条机器指令,交付时间一推再推,直到 1957 年 4 月才随第一批 IBM 704 交到客户手中。进度失控、规模失控、没人真正知道"做完"长什么样——这些后来软件工程教科书里的经典症状,在 1950 年代曼哈顿的 IBM 办公室里全部预演了一遍。

巴克斯此前为 IBM 701 开发的 Speedcoding 解释系统给了他关键直觉:解释执行让程序员省去手写浮点代码之苦,但性能损失巨大——一般编程可以忍受,科学计算却付不起这个代价。而 IBM 704 恰好有了硬件浮点与变址寄存器,"解释"这条退路被彻底堵死,唯一出路是把编译做到接近手写汇编的水平。所以 FORTRAN 的编译器从第一天起就是围绕优化器设计的:易用性吸引用户,效率说服怀疑者,两者缺一不可。

BNF:描述语言的语言

1959 年,在巴黎举行的 ALGOL 60 语言设计会议上,巴克斯提出了一种用符号描述编程语言语法规则的方法。彼得·诺尔(Peter Naur)在整理 ALGOL 60 报告时改进了这套符号,后来这种方法被称为巴克斯-诺尔范式(BNF,Backus-Naur Form)。

BNF 用以下形式描述语法:

<表达式> ::= <项> | <表达式> "+" <项>
<项>     ::= <因子> | <项> "*" <因子>
<因子>   ::= <数字> | "(" <表达式> ")"
```

意思是:表达式可以是一个"项",或者"表达式 + 项";项可以是"因子"或"项 * 因子";因子是数字或括号内的表达式。

这个递归定义系统可以精确、无歧义地描述任何编程语言的语法规则。它与乔姆斯基的形式文法理论高度吻合(上下文无关文法),成为了编译器理论、语法分析器生成器(如 yacc、Bison、ANTLR)的理论基础。

今天,几乎每一种编程语言的官方规范都包含 BNF 或其扩展(EBNF)形式的语法定义。 你在 JavaScript、Python、SQL 标准文档里看到的语法描述,都来自巴克斯在 1959 年的这项工作。

图灵奖演讲:对冯·诺伊曼瓶颈的批判

1977 年,巴克斯获得 ACM 图灵奖。他的获奖演讲《程序设计能从冯·诺伊曼风格中解放出来吗?》("Can Programming Be Liberated from the von Neumann Style?")是计算机科学史上最著名的演讲之一。

他的核心论点:

冯·诺伊曼瓶颈(von Neumann Bottleneck):传统的命令式编程(用赋值语句逐步改变内存状态)迫使程序员一次只操作一个"字"(word)的数据,通过"获取-操作-存储"的循环与内存交互。CPU 和内存之间这条单一的数据通道就是瓶颈——在这种模型下,并行计算和数学上的清晰性都很难实现。

函数式编程的替代:他提出了一种叫 FP(Functional Programming)的语言,程序不是操作可变状态的命令序列,而是函数的组合——就像数学中函数的组合那样,每个函数是纯粹的、没有副作用的,输入输出完全由函数本身确定。

这个演讲在 1977 年没有立即改变行业。但四十年后,当 JavaScript 的 .map()/.filter()/.reduce()、Scala 的 Spark、Haskell、Erlang 和无服务器(serverless)计算兴起时,"函数式"成了热词——而它的系统性批判,早在巴克斯 1977 年的演讲中就已提出。

这个演讲里还有一层常被略过的技术主张:程序组合的代数。在命令式语言里,两段程序拼在一起的性质无法从各自的性质推出,因为每一段都可能读写共享状态;而在 FP 里,程序由少量组合形式(组合、构造等)把函数装配而成,组合形式的代数规律使"用等式推理程序、机械地做等价变换"成为可能。巴克斯要的不只是换一种语法,而是恢复一种能力——像数学家推理公式那样推理程序。今天编译器对纯函数的自动并行化、Spark 对 map/reduce 管线的优化,用的正是这条推理通道。

晚年与平静的离去

巴克斯在 IBM 研究院工作到退休,晚年生活低调。2007 年 3 月 17 日,他在俄勒冈州阿什兰的家中去世,享年 82 岁。

他获得的奖项包括:1975 年美国国家科学奖章(National Medal of Science),以及 1977 年 ACM 图灵奖("为了对 FORTRAN 及编程系统的设计做出的深刻、有影响力的持久贡献,以及通过 FORTRAN 和形式化程序设计语言规范过程(BNF)的发展对编程语言的贡献")。

跨域连接

  • 句法学:他的产生式记法与乔姆斯基的形式文法是同一套形式系统被两个学科同时用到,目标却正好相反:语言学要找一个能生成自然语言、又尽量受限的文法,语言设计者可以直接规定文法,把歧义排除在门外。对照因此很干净——自然语言的歧义只能靠语境消解,编程语言的歧义可以在设计阶段禁止。
  • 函数:数学里的函数由输入唯一决定输出,因此等值表达式可以随意互换;命令式程序里的"函数"依赖并改变状态,替换性一旦失效,任何推理都必须扛着整个状态走。他对冯·诺伊曼风格的批评就是要把这条替换性还给程序。收益也正在此:满足替换性之后,重排、缓存与并行才对编译器开放。
  • 决策心理学:管理层怀疑编译器生成的代码不可能追平手写汇编,结果它追平了。原因不是编译器更聪明,而是它更一致——在规则明确的重复任务上,机械执行常胜过专家判断,因为专家的额外信息抵不过不一致带来的方差。这条推论至今有效:越是重复且规则清楚的环节,自动化的收益越来自方差下降。
  • 量子化学:数值模拟代码的寿命远长于硬件与语言时尚,原因不在语法。它的价值沉在被反复验证过的数值行为里,重写就等于把这份验证一并丢掉。所以迁移的真正成本是重新建立对结果的信任,而不是转换语法——这解释了为什么最老的语言仍占据着最前沿的计算。
  • 形式文法与乔姆斯基谱系:产生式记法把语言规范从散文变成了可判定的对象:由文法可以机械生成语法分析器,也可以判断一段语法是否有歧义。边界也随之划定——超出上下文无关的部分只能靠额外上下文补救,这正是若干语言里"看似语法问题其实要查符号表"的来源。

参考文献

  • Backus, J. Can Programming Be Liberated from the von Neumann Style? A Functional Style and Its Algebra of Programs. Communications of the ACM 21(8) (1978): 613–641. (图灵奖演讲,开创函数式编程讨论)
  • Backus, J. et al. The FORTRAN Automatic Coding System. Proc. Western Joint Computer Conf. (1957): 188–198. (FORTRAN 的原始技术描述)
  • Backus, J. The History of FORTRAN I, II, and III. ACM SIGPLAN Notices 13(8) (1978): 165–180. (巴克斯本人对 FORTRAN 研发过程的回顾)
  • Naur, P. et al. Report on the Algorithmic Language ALGOL 60. Communications of the ACM 3(5) (1960). (BNF 的第一次正式使用)