7. 程序流程控制的结晶:结构化程序设计

忽软忽硬
忽软忽硬
7. 程序流程控制的结晶:结构化程序设计
/

我们用的编程语言,都有类似于if、while、for等来控制程序的流程,以今天的眼光来看,这是理所当然的事情,就好像家用汽车就应该有4个轮子,手机就应该有个大大的屏幕一样,但是,在以前,并不是这样。

这一次对所有编程的人来说,都非常的“浅显”,编程的时候,要用结构化编程,用顺序,循环和选择这三种结构,就能搞定任何编程,不要再想其它的结构。

我上来先说几篇论文的,都是在1966年左右发表的论文,这两篇论文实在是太出名了,你在Google上都不用打上全名,打一半就给你补全了。第一篇是1966年发表的《Flow diagrams, turing machines and languages with only two formation rules》,如果有人想看的话,收获肯定很大,我再讲一遍我一直以来的理论,以我的见解,出名的计算机科学家中,除了图灵老先生的论文读不懂以外,有一本书专门帮忙解读图灵的论文。其它人的,都非常简单,越出名的人写的越简单。尤其是现在,这些科学家写的论文,是编程的蛮荒时代,给编程指明了前进的方向。现在再读,你会觉得,这样也能写论文,这不都是些常识么?

这一篇论文讲的内容,总结一下就是,任何一个goto语句,都可以改为完全不使用goto的语句。说实在的,这篇论文引起的争论并不够大,原因是这两个作者的名气不够大。不是学术网红。

随后,1968年3月,计算机界接近最大的那几个大佬之一Dijkstrad,这个哥们在计算机学术界是顶流,在同样一份《Communications of the ACM》上,发表了名为《Go To Statement Considered Harmful》的文章。这篇文章引发了长达4年的争论,小人物就不讲了,获图灵奖的人都要出来发表自己的看法。这篇论文的意思是:每个方法、方法中的每个代码块都应该有一个入口、一个出口。遵循这些规则,意味着在每个方法中只该有一个return语句,循环中不能有break或continue语句,不能有任何goto语句。

主要的内容是我总结的,论文确实是说了这样一件事,但是我仍然认为,如果你读了,就不止知道这条结论,还会懂得来龙去脉。我之所以总结一下论文的内容,是因为我知道有很多人不肯去看论文,也不肯去读书。

现在有一种节目叫帮你读书,尤其是那些名著,一般人不喜欢读,于是就有人用1-2分钟给你总结书的内容。这种做法跟我前面总结论文的内容差不多,就记住了个结论。说实在的,相比于一般人,我看书很多,几乎所有有点名气的名著,我都读过。如果我要给大家总结的话,大概会是这样:《漂亮朋友》讲的是一个帅哥,为了能爬到社会的顶端,不停的跟女人上床,最后,成功了的故事。《红与黑》讲的是一个帅哥,为了能爬到社会顶端,不停的跟女人上床,最后,良心发现,不能再靠女人了,最后被杀了。《一个女人的来信》讲的是一个女人为了爱一个男人,可以做到有多么卑微,连生了孩子都不肯告诉男人,并且,这个男人因为睡了太多的女人,甚至不知道给她写信的人是她睡的哪个女人(这让我想起了城哥)。《巴黎圣母院》讲的是一个丑男,为了自己爱的女人,可以做到有多么卑微,虽然这个女人从来没有爱过他,并且女人被她爱的男人害死了,但是最后这个丑陋的男人还是抱着女人的尸体,一起躺进了坟墓。《罪与罚》讲的是一个穷小子,杀了房东和她的妹妹,最后坐了监狱,出狱后过上了幸福的生活。《苔丝》讲的是一个姑娘,杀了强奸她的男人,最后她也被杀了。(多讲一句,《苔丝》是我读的第一本全英文小说,全本的那种,不算书虫那种缩写版。原因不是我多么喜欢英语,而是我先读的书虫那种缩写版,里面写强奸的部分一句话带过,我又找了翻译版,里面写强奸的部分也是一笔带过,我当时在高中,我意识到,妈的,这帮家伙肯定有问题。那时候不好搞原版书,但是我心里一直记着苔丝这个姑娘,为什么在第四章里去了树林里,在树林里睡着了,然后发了不可描述的故事。直到我大学里找到了原版,迫不及待的翻到第四章,TMD,原版书里也是一句带过…..但是,我还是看完了这本英文书。)

如果我这样讲名著,就一点意思也没有了。同理,论文也是如此,希望听众在听到以后,有1/100的人,真的去读了原版论文,我录电台也就有了第二重意义。

有人可能会有疑问,说这种编程语言不都有自己的ISO标准么?ISO标准基本是一个事后标准,跟我们认为的一些文件不同。比如我们经常会在新闻里听到类似于《指导意见》的政策,这种指导意见一出来,虽然名字叫指导意见,但是如果你不听指导,那就有你的好果子吃。在编程中,完全不是这么回事儿,每个编程语言都要出自己的ISO标准,这个标准,是看到大部分人都这么用,然后再把约定成俗的写成ISO发给大家参考。

这一点很重要,是发给你参考,如果你认为ISO标准是SB,你可以不用理,继续用你的方法。所以,以下我讲的东西,你可以遵守,也可以不遵守,这是编程语言中的常态。而且每一种方式,背后都有不同的大佬支持,以C语言为例,如果大家知道goto语句的话,可能会知道一般书上不建议使用goto语句,但是写《计算机编程技术》的高德纳和写Linux的大喷子Linus,就喜欢用Goto语句,这一点毛病也没有。

Linus曾经说过这样一句话:标准都是垃圾。大家知道这句话的来历么?我花点时间讲一下他老人家被砸的经历吧。

我记得当年,Linus还没有被砸的时候,Linux内核的开发者绝大部分都是男的,因此,Linux的内核文化圈中,脏话满天飞,这些老直男能忍受这个。当时,有一个叫Sarah Sharp的内核开发者,当时这个人还是个姑娘,她开发了USB 3.0的驱动。后来这个姑娘留起了胡须,络腮胡子,当然了,也不能说她是男的,她说自己是non-binary,分二元性别,可能国内对这个不太熟悉,我也不太熟悉,我看网上说不能用男女来区分所有的人。

这个家伙还是女人的时候,她要改变Linux社区脏话太多的状况。于是,他搞了一份类似于社区公约的文档,从道德上来约束这些核心开发者,像妈妈教育小孩一样,不能说脏话,妈的,你听到了没有,不能说脏话。结果呢,Linus本人不太感冒,而且事情的起因是Linus骂过这个Sarah,他觉得Sarah是个事儿逼,那次辱骂直接把Sarah给骂的要退出Linux内核开发,但是显然Linus根本不在乎她会不会退出。

就跟骂我做电台的那些人一样,你再这样,我就取消关注。当然了,Linus更加的无礼一些,在邮件中说了一些fuck,你TMD闭嘴吧,标准就是个垃圾。这句话大家可以记一下,Linus本人根本就不在意C语言的ISO标准,希望大家在达到Linus的程度以后,也说一句类似的话,如果远没有达到,那还是尽量按照C语言的标准来写,会比较好。

Sarah就有点受不了了,威胁我要把我写的代码撤回,但是她提交的代码并不是特别的有重量级,就是一些驱动程序,就算把她提交的代码都撤回,Linux没太大区别。但是,显然这个姑娘不简单,她写了一篇文章,直接把Linus给拉下水了,她说Linus不尊重女性。Linus不尊重女性这是肯定的,以他的嘴,他不止不尊重女性,他也不尊重男性,也不尊重公司,反正,在他的眼中,就没有值得他尊重的东西。然后媒体口诛笔伐,直接导致了Linus本人于2016年宣布了退休,纽约客还采访了Linus本人,大家可以去搜一下。后来Linus不尊重女性这件事情过去以后,Linus默默的复出了,然后嘴巴干净了许多。

随后,Sarah就搞了一个什么类似于社区文明礼仪的文档让大家签署,Linus马上就签署,其它几个核心人员也签署了。但是,有一个刺头,他的名字叫Theodore Ts’o,他是个华裔,有个中文名字叫曹子德,这哥们,也可以称之为广义上的蝈蝻了,毕竟姓曹名孟德,不, 姓曹名子德。他不签署这个协议。 他对开源的贡献极大,我们现在用的Linux文件系统,都是他主持开发的。

在中国,如果你讨厌一个人,想让他社会性死亡,应该怎么办?最好的办法是找到他的社交媒体,挨着挖坟,总有几句是政治不正确的。这个Sarah也精通此道,2018年的时候,她说这个曹子德为强奸犯辩护。这条twitter目前还在,大家有兴趣可以去看看,我截个图。

我又看了为什么他会替强奸犯辩护,其实,并不是这么回事。这个小曹,只是看到了网上一篇文章,那篇文章给了一数据,如果他在中国的话,不会这么激动,中国媒体经常为了吸引眼球,写一些类似《中国女性77.5%被性侵过》《中国男性58%是强奸犯》《中国有1/3的孩子不是亲生的》,这种叫标题党,根本不值得去反驳。但是小曹没经验,他认真的反驳了一篇类似《中国男性58%是强奸犯》的标题党文章,他说不会这么高的比例,这也不符合常识。于是,一顶帽子就戴在了他头上。

反正,凡事都要小心吧,就不多扩展了。继续讲编程的控制流程,大家记住,Linus说的那句话:“标准都是垃圾”,即使大部分情况你要按照标准办事儿。你要在必要的时候,勇敢的打破标准对你的禁锢。

如果大家听过我讲的上一期的BNF的话,有一个听众听了以后,真的去图书馆里借到了一本叫《
C语言BNF解译及其程序设计》的书,虽然我不清楚这个听众会不会真的看完这本书,但是书都是如此,只要了解大体意思就可以了。我确实没办法在电台里讲清楚BNF是个什么东西。

这一期也是如此,我没办法,也没必要讲if,else这些控制语句,我宁可讲一点我学习时候的故事,希望能对有兴趣的人一点启发。这个故事来自于我学习C++的时候,对我来说,C++是超出的理解范围的。

每种编程语言都有自己的语法,当年学编程的时候,很苦恼,这么多语言,怎么能学得过来呢?当时我在学C++,有一天,我想找点别人写的C++来读一下,就在一个叫sourceforge上的网站上乱逛,看到了一个项目,项目的名字叫Gcc-XML。

容我讲一下这个项目,让大家了解一个背景。

在1999年的时候,美国国立卫生研究院(National Institutes of Health,NIH)要做一个项目,要把人体数字化。一位因病去世的女性参加了这个计划,人体被切割成0.3毫米左右的切片,然后用高清相机拍照后,重建整个人体,这个项目大概产生了65G数据。

为了处理这些数据,研究人员使用C++语言写了一个项目,最终项目产生了160多万行C++代码,这些代码被广泛使用,增加功能,越来越难以维护。NIH的研究人员越来越多的使用Python语言,用Python语言的swig来和这些C++代码交互,直到有一天,他们觉得要是把C++的代码全部改写成Python代码就好了。

这可不是一万行代码,而是一百多万行C++代码,工作量可想而知。

有没有办法把C++代码转换成Python的代码呢?于是他们就有了这样一个项目,项目最初的名字叫Gcc-XML,现在已经改名为CastXML了,有兴趣的可以到github上看一下。项目的目标是把C++代码转换成Python代码。

当时我已经学会了Python,正在学C++,对C++转换成Python有浓厚的兴趣,就读了该项目的代码,大体了解了其工作原理。原理是这样的:使用Gcc-XML对C++代码进行处理,生成中间状态的代码,然后再根据生成的中间代码,使用pycxml转换成Python语言。

当年我孤陋寡闻,一直学不好C++,看到有人能直接把C++转换成Python代码,惊呆了!我就想搞明白他们是怎么做的。于是我就写一段C++代码,然后用Gcc-XML转换成中间代码,然后再转换成Python代码,整个过程乐此不彼。

我很少沉迷于技术,除了这一次。一般情况下,只有我在玩游戏的时候,突然一转头,天亮了,玩了一晚上,比如玩《文明》的时候。这次竟然是学编程,我搞了一个通宵。

在查看中间代码的时候,我意识到这样一问题,从道理来说,根据这些中间代码,C++不止可以转换成Python,只要你写的代码足够精妙,巧妙的避开其它语言中不存在的特征,C++可以转换成其它任何语言。想法再远一点,任何语言都可以转换成另外一种语言。

当我有这个想法以后,呼吸都开始急促了,我无意之中发现了一个可以统一一切的语言,只要按照中间代码的方法搞出一种编程语言,比如dong语言,我这个语言就能一统江湖了。但是这个想法在我脑子里停留了没多久,我就发现,这种中间代码每个学过计算机的人都知道,学名叫抽象语法树(Abstract Syntax Tree, AST),这个抽象语法树也就《编译原理》这门课主要讲的内容之一。 虽然想创造一种统一江湖的dong语言的梦想破灭了,但是在我重新发现抽象语法树的那一刻,我觉得我对《编译原理》产生了某种顿悟(也可能是某种误解),我们上课时候老师花了大量时间讲解如何构造一个语法解析器(parser),实际上,这东西一点也不重要。如果说构造出一个编译器是万里长征的终点,那把语法解析成抽象语法树这个阶段是万里长征的第一步。

老师上课为什么不讲重要的东西呢,我觉得有两个原因,第一个原因,老师是一个职业,他也不想深入研究这玩意,他其实也不会深入的东西,按照我目前的经验,大部分计算机系的老师其实做不了大一点的软件,而且是逆淘汰的,越有技术的,你就越当老师,反而当不了领导,技术是个负资产,这个道理在大部分公司也适用。第二个原因,学生不想学,就算老师会,面对不想学的学生,也真的是懒得教,现在这个人人都有手机的环境下,谁愿意讲深入的东西?所以,讲如何构造一个语法解析器就可以了,不用再深入讲了。毕竟这个东西,介于难与不难之间。

这一期讲结构化编程,这已经融入到我们日常编程中了,以至于每个程序员都觉得,编程就应该这样。这其实是好事,就像空气一样,你感觉不到它的存在,但是却无比珍贵。

4人评论了“7. 程序流程控制的结晶:结构化程序设计”

  1. AST是程序的本体。编程活动就是对AST进行“编码“,各种编程语言只是一个载体,计算机(编译器/解释器)将编码(代码)再”解码“成AST执行。

  2. 哈哈,我上次听完也找到了《C语言BNF解译及其程序设计》这本书,1986年的,孔夫子有两本旧书,googlebook也有些信息,可惜的是找了半天,连个目录都没找到。。。

发表回复

您的电子邮箱地址不会被公开。