关于编程语言的一些趣史

关于编程语言的一些趣史

回顾历史做仔细的分析与研究,总能给人意想不到的发现和惊叹。从认知的难易程度上来看,编程语言的范式可以按照如下的方式排序:最容易理解的是structured programming,一根线从上往下;再来会稍微费点功夫理解的是object-oriented(OO)programming;更困难的是functional programming,相当抽象,整个就是一数学的抽象思维。

自然地,历史的发展都是由简单到复杂,我们会下意识地认为编程语言在历史上的出现顺序也应该是:structured programming、OO、functional programming。

但翻阅历史,却会惊讶地发现它们的出现顺序竟然是反过来的!

  • structured programming是在1968年出现,其标志是Dijkstra(对,那个最短路径算法里出现的名字)发表他的seminal paper ‘Cooperating sequential processes’。
  • 再来是更早的1966年,Dahl和Nygaard发现function call stack frame可以被放到heap去做,这标志着OO的出现。
  • 而似乎最难以理解的functional programming,则几乎可以追溯到1936年计算机被发明的时期。其标志是Alonzo Church推出lambda calculus。

另一件值得探讨的事情是:为什么Dijkstra要引入structured programming?虽然从现在来看structured programming是如此的直观,以至于你会问,为什么会过了那么久才引入structured programming?

在Dijkstra的时代,主流编程语言都不是structured的,到处充斥着goto所带来的跳转。为什么会遍地的goto呢?因为在计算机语言的莽荒时期,一切都是向机器看齐的。对于机器语言、汇编来讲,指令集的各种jump操作是再平常不过的事情了。既然它们都有之灵跳转,对应的编程语言怎么好意思说不支持goto呢?

所以,structured programming反而在当时是一种极端的非主流,因为它为programming给予了相当大的限制。

Dijkstra之所以要引入structured programming源自于他要把“计算机”这门学科变为科学的尝试:将数学的公理化体系引入computer science(CS)。但经过大量尝试后,他发现要为代码构建牢固的数学公理体系着实不是一件容易的事情。而其中最大的问题障碍,就是goto带来的不确定性。

于是,Dijkstra采用了数学家常用的研究方法:当需要推出一个漂亮的理论却发现前提条件不够时,就反过来先引入这个结论需要的前提假设。

于是,Dijkstra就直接把goto(至少是被滥用的goto)废除掉。没有了goto,虽然引入数学的严格证明会变得相当简单,但这样会不会限制语言的表达?又或者说,有些代码是不是没有了goto就无法写出来呢?

说来也是历史机缘,恰好在这个时候,Bohm and Jacopini在理论上证明了:所有的程序都可以被以下三种句式所替代: sequence, selection(if/then/else), iteration(for/while)。而这正好是Dijkstra所需要的,因为实现这三种语句完全用不到goto。于是,Dijkstra的为CS引入严格数学公理体系的壮举也就水到渠成:所有的由sequence、selection(if/then/else)语句构成的程序,可以由数学枚举法证明。而由iteration(for/while)语句构成的程序,则可以由数学归纳法完成。而structured programming这种被做了更多限制的编程范式也就应运而生。(很有意思的事情是,三种编程范式structured programming、OO、functional programming的引入,都是通过“限制功能”而非增加功能做出的,也即是,为了更强你需要更弱一点。更多讨论可以参考我以前的一篇文章《为了快一点为什么却要慢一点》。)

如果按照这样的思维框架去思考算法,比如LeetCode中的算法题目,又会有一些惊人发现。我的一个想转行做程序员的朋友曾跟我聊过这样一段刷题感受:似乎算法题目都或多或少地在使用数学归纳法。这确实是很强的洞见。回顾起来,无论是divide-and-conquere还是dynamic programmming,这两种作为算法基石的工具都运用到了数学归纳法的思维方式。前者(递归)是天然的数学归纳法处理方式,而后者则是做了空间复杂度优化的递归,同样按照数学归纳法的方式做处理。

进一步,我们可以考察一些工作中遇到的问题。刚毕业工作的小白程序员常常会疑惑这样一个事情,明明自己在学校中算法的造诣颇高,按道理说算法好不就是编程的功底好么,但为什么到了工作岗位中还是各种碰壁?

按照我们上面构建的思维框架,我们其实可以给出一种解释:因为算法部分的修炼,仅仅保证了你在structured programming这个语言范式下做事具备了很好的能力。可工作中所涉及到的软件设计,则是在OO范式和functional programming范式下进行的。领域不同,自然是新手,碰壁也是自然之事。

再回到我们最开始的那个问题,为什么编程范式会是以相反的认知方向来发展?因为这是按照“构建计算机领域”的难易程度在走,也即是背后的数学发展在展开,而不是编程语言使用的难易程度在发展。这是一门新兴学科初期的发展特点——先考虑的是生产的便利性,再来是消费者的便利性。

========

Comments for 《Clean Architecture》

 

 

 

近期回顾

他人皆蠢,吗?
从Facebook面试看互联网行业
GeekArtT两周年

 

如果你喜欢我的文章或分享,请长按下面的二维码关注我的微信公众号,谢谢!

更多信息交流和观点分享,可加入知识星球:

发表评论