zoukankan      html  css  js  c++  java
  • 关于编程语言的一些趣史

    回顾历史做仔细的分析与研究,总能给人意想不到的发现和惊叹。从认知的难易程度上来看,编程语言的范式可以按照如下的方式排序:最容易理解的是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两周年

     

     

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

       

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

  • 相关阅读:
    手机体验细节小动画
    第一次用AngularJS
    鼠标离开方向检测
    回忆之placeholder
    回忆之日历
    大数据学习
    shell 二
    十三:变量、函数、存储过程、循环控制结构
    十二:事务与视图
    十一:约束
  • 原文地址:https://www.cnblogs.com/kid551/p/9840321.html
Copyright © 2011-2022 走看看