4. 编程语言中的中流砥柱

谭嗣同就义的那天,9月28日,我正在公众号里写一篇文章,纪念一下这个伟大的人,顺便推荐一本书,台湾那个李敖写的《北京法源寺》,结果正写到一半,浏览器退出了,最初我以为是Chrome浏览器崩了呢,后来发现没那么严重,仅仅是公众号被封了,文章也就没法发表了。

我觉得我自己搞个电台吧,就搞了一个叫《忽软忽硬》的新电台。用到了一点点技术,有听众来问我,他也想搞,应该怎么搞?我才发现,有些人,还是读计算机相关专业的,技术真是太拉跨了,属于听过但是不会弄,或者连用个Linux都相当费劲的情况,这样就很难搞了。而且有人听到我是用的PHP做的,就表现出,我操,你也太弱了,连PHP都敢用的态度。PHP不是很烂么?

我决定讲一些计算机编程的知识,不限定语言,但是以Java语言为主。原因我一会儿就讲为什么以Java语言为主来讲编程的知识。

中流砥柱是一个常用的成语,我100%相信大家听过这个成语,有些人喜欢自称自己是中流砥柱。这句话的原本意思是,大禹治水的时候,有个地方叫三门峡,有两块巨石头,分别是神石和鬼石,把河道分成了三个门,分别是神门,人门和鬼门。今天大家去三门峡的话,只能看到一块石头,这块石头就叫中流砥柱,说大禹治水的时候,放下的定河的石柱,用来镇住鬼门里的魑魅魍魉。那块石头其实不算大,尤其是它旁边有个叫张公岛的小岛,相比之下 ,更小了。那以前神石和鬼石呢,因为要修三门峡大坝,被修在大坝里面了。我去过这个地方,山西和河南交界的地方,还有个标志标出了省的界限,就在那个大坝上。(以上都是N年前我去旅游的时候,我蹭人家导游听来的)给我最大的震撼是,三门峡水库是黄河第一坝,那水是真的清绿色的,一点也不黄….

总之,中流砥柱就是千年不变的东西,代表了一种精神,万年就不好说了,在风和水的冲刷下,别说石头,就是山也能给你削平。

我这里讲编程语言中流砥柱的意思,是讲其中不变的特征,而不是说哪门语言是中流砥柱。在这里我以Java语言为主要的例子来扩展到其它我知道的语言中,为什么先Java呢?而不是选Go语言,不是选Python语言?

我稍微介绍一下吧,我在有些微信群里,经常会有没素质的网友发一张有好多美女的照片,然后问同样没素质的群友:你们会选哪个?最后总有最没素质的群友说:小孩子才做选择,我全都要!

如果把编程语言的特征当作一个又一个的珍宝的话,那么,不同的编程语言实际上是做出了不同的取舍。据我所知,有三门语言就是那种“小孩子才做选择,我全都要”的编程语言,这三种语言分别是:Perl,C++和Java。这三门语言几乎支持所有的编程范式,其中的Java是相对比较收敛的,比如不支持多重继承,但是又引入了接口等等来变通。如果我在这些节目中选择Go语言,那就没法讲了,原因是Go语言从一堆宝贝中,选的比较少,比如Go语言没有继承,目前还没有范式(我相信以后应该会加上范式),没有重载,没有命名参数……反正,有很多特征在Go中是不支持的。所以,我只能以某种“我全都要”的编程语言来串讲一下。

说实在的,如果你能学会一门“我全都要”的编程语言,再学习那些“我只其中一个或者几个”的编程语言,是非常容易的。我再分享一个我的观察,如果一个人是写动态语言的(Python,Ruby,PHP)这些的,一旦工作需要,不得不写C/C++/Java,(这对打工人是常事,老板让你接手一个项目,你总不能说老子看到Java就烦,然后辞职了…除非你家里有矿),那么,写出来的C/C++/Java的bug一定很多。如果一个是写C/C++/Java的,因为工作需要,不得不写动态语言,那么,他写出来的代码一定是非常的复杂,其中看不出动态语言的优点,而且不但心里鄙视PHP,Python,嘴里也多半不干净。这只是我的观察,没有什么依据,大家可以看看自己身边的同事,是不是这么肥事,也不要找我来理论。我本人,写动态的,写静态的,都是垃圾,bug多,不优美。

大家不要认为写bug是缺点,其实是优点。我兄弟三人在同一个公司工作,我大哥水平最高,写代码之前先总体规划,从架构上就杜绝了bug出现的可能,然后默默无闻的在小组里码代码。我二哥水平稍差,但是借助IDE这些编译器,在写代码的时候,也能找出bug,顺手就解决了,然后在小组里有点小名气,大家知道他是调试高手。我,栋哥,水平最差,写代码是意识流,写出来的代码经常是这台电脑能跑,换一台就卡了,业务量少的时候能跑,业务量多的时候就挂了,不但小组里受拖累,还影响了全公司的业务,一有问题,全公司找我解决,我完美的解决了我大哥二哥代码里不会出现的问题,那bug,按下葫芦浮起瓢,领导看在眼里,记在心里,认为我是全公司的救火队员,水平肯定最高,就让我当了公司的首席技术官。

美国的独立宣言有这样一句话:我们认为以下真理是不言而喻的:人皆生而平等,享有造物主赋予给他们的不可剥夺的权利,包括生命、自由和追求幸福的权利。为了保障这些权利,才在人们中间建立政府,而政府之正当权力,则来自被统治者的同意。

我想把这句话篡改一下,放在编程的环境里: 我们认为以下真理是不言而喻的:程序员皆生而平等,享有编程赋予给他们的不可剥夺的权利,包括运行速度、可移植性和程序安全的权利。

我默认所有的程序员和编程语言都追求这三方面:运行速度要快,可移植性要高,还有保证程序安全。如果你不追求这三方面,像有人认为美国独立宣言就是些漂亮话,要自由干啥,能当饭吃么?那咱就聊不下去了。编程语言能不能同时达到运行速度快,可移植性高以及程序安全,这个再说,但是至少要有这方面的追求。我认为没有语言是追求运行速度慢,不可移植,bug成堆的。这个也太没追求了。

这三项,我称之为编程语言的中流砥柱。

为了达到这三项,是相当困难的,因为这三项本来就是有冲突的,为了运行速度快,势必会导致可移植性不高(兼顾了x86平台的速度,可能会拖慢ARM平台),如果为了保证安全,又要多很多检查,从而会导致运行速度又不够快。总之,一定要很好的权衡,才能在编程语言的历史上留下些许痕迹,现在的编程语言,如果不是数以万计,也要数以千计,但是我们听说过的编程语言,也就那么几种,会用的,两只手数的过来。编程语言行业,也非常非常的内卷。

编程语言有一些核心的概念,是所有主流语言都要考虑的,类似于我们上大学的必修课,管你什么专业,马克思主义哲学都要学。在编程语言中,也有类似的科目,比如所有的编程语言都要支持程序的控制流程,可能不同的语言有所区别,但是这些东西你都得有。就像汽车都要有轮胎,大学生都要学习马克思主义哲学一样。

目前,我总结了一下大部分主流编程语言都支持的一些特征,在接下来的几期里,我想考证一下这些“中流砥柱”的历史,以及不同的语言给出的答案。以下这些条目是我目前想到的,随着节目的进行,可能会有所增加,到时候再说。

第一个部分是变量名与作用域。主流的编程语言都要有变量,而有了变量,就要考虑变量名的作用域,大家可不要以为这个非常简单,在这里是出现过大型翻车现场的,伟大的Perl语言——这个曾经高居编程排名第二的语言,在处理变量和函数的作用域的时候,车子翻了好几圈,从Perl 4开始翻车,一直翻到Perl 5,在Perl 4中引入了local关键字,在Perl 5中引入了my关键字,就是为了解决变量作用域的问题,当然了,没解决好。

那你可能说,我又不用Perl,我是用人见人爱的Python。不要那么幼稚,Perl解决不好的问题,Python中也解决不好,Python 3.0中引入一个关键字叫nonlocal,就是为了解决作用域的问题。当然了,我做这些音频的目的不是为了引起争吵,我不是为了争吵静态作用域好还是动态作用域好,而是想引起大家的思考。如果你同时写过静态语言和动态语言,并且你用过重构的功能,你就会发现,在动态语言上几乎是没法重构的,在Python项目里,连最简单的变量名替换,都是不安全的。比如有个变量名叫liuyandong,你想把他替换成wuyanzu,在Python/Ruby这种项目里,是不安全的。因为动态语言都宣传的“咱家的语言有‘late binding’–正宗的面向对象–功能”,正是因为有这些功能的存在,导致了这里的liuyandong和那里的liuyandong两个变量,是不是同一个变量,成了一个不可判定的问题。到时候,我们共同探讨一下变量的历史,以及对变量采取不同的策略,各自会产生什么样的问题。

还有一个是类型。几乎所有的编程语言都会谈到类型,但是只肯给类型一小段的内容,好像这件事情一点都不重要一样,实际上,类型太重要了。如果你是在华尔街这样的地方,那种玩大钱的地方工作,你就不能用浮点数,而是用定点数或者加三码这样的十进制计算方法,因为浮点数对玩大钱的人,是不够精确的。比如马云,稍微一点不精确,人家的财产就差了数十万。

之所以我们觉得类型不重要,是因为解决类型问题的时候,远在1970年代,问题解决了。当年也是一锅粥,到时候我会讲一点远古的历史,在类型问题没解决的年代,编程语言是如何处理类型的,比如我也不知道大家知道有个编程语言叫FORTRAN么?这个语言的作者叫约翰·巴科斯,是个花花公子,虽然他发明了FORTRAN,算是世界上第一个编程语言,但是他老爸比他厉害的多,他爸爸自学成才,二战时期赚了大钱,他爸开的公司,专门给美国提供炸药。二战结束以后,炸药销量锐减,他爸转行又去了华尔街,开证券公司,然后,生了这个每学期只选修一门课——音乐欣赏——的儿子。又讲多了,FORTRAN语言如何表示类型呢?强行规定,以变量I到N这六个字母开头的单词,表示为整数。除此以外,表示为浮点。

这种表示方法当然有点山寨感,C语言对其进行了改进,成了我们今天看到的大部分语言学习的样子。比如在C语言中,5/2=2,而不是2.5,这虽然在程序中是这么规定的,但是仍旧反直觉,你拿这个去糊弄2年级的小孩,他也知道,4/2=2,5/2肯定比2要大。1991年才问世的Python,也沿用了C语言的风格,但是到了Python 3.0,5/2=2.5了,如果想用C语言的方法,得写成5//2,要用两个反斜杠。

类型非常重要,尤其是目前的电脑是用二进制来表示的。比如,有个人包养了一个小三,说好的每天1000块钱,结果这个月给了小三30000块,小三不干了,说你说好的每天1000块,这个月是31天,你只给了30000,那相当于每天是967.74,每天差一杯奶茶钱呢。我们来看一下这句话中的数字,先来说小三的这个三,这个是名词,在计算机中应该表示为字符类型。还有谈好的每天1000块,这个是整数类型,少给了1000的,结果成了每天967.74,这个数字是浮点类型,在计算机中要表示为浮点数。这短短的一句话,每一个成年人,自动在脑子里对这些数字进行了切换。

大家再来思考一下,我前面讲的那三个中流砥柱:速度,可移植性与安全性。然后考虑一下下面的问题。

不同的语言对此的处理方式非常不同,以C语言为例,你存就存,你把每天的967.74存到溢出了,我也不管。所以C语言很快,为什么很快?因为不管所以快。这就是典型的追求速度,但是可移植性不够好,不同的平台对类型都有不同的定义,安全性更是不考虑。

以Java为例,当然,java也会溢出,没有语言是完美的,但是比C语言难以溢出,具体的操作方式以后再说,Java有自动的类型提升,int型换成long型,long型转换BigDecimal类型。因为有转换,Java是不是要慢了一些?但是移植性更好了一点,也更安全了一点,用牺牲的效率换取了更好的移植性和安全性。

再加上面向对象编程,当然,是支持面向对象的编程语言,像Go语言目前还不能,以后谁知道呢,像PHP语言起初也不支持面向对象,还一度觉得面向对象没什么用,但是后来也支持了。面向对象编程中,程序员自己定义的类,也是一种新的类型。

我还列出了几项我认为是中流砥柱的知识点,这一期讲不完了,要不然时间太久了。分别是:

  1. 表达式
  2. 函数
  3. 程序流程控制
  4. 错误处理
  5. 面向对象
  6. 容器
  7. 字符编码
  8. 并发处理

这8个方面,外加前面讲的2个,我总共总结了10个方面的内容,主流的编程语言,都要处理这10个方面中8到10个。

我打算把这10个方面的内容,每个方面做个1-2期电台,以Java为主,因为Java全部涵盖了,它是一门什么都要的语言。而且,Java的工作机会要多于其它语言。

本期节目进入我最讨厌的阶段了:给人提意见。我很讨厌别人给我提意见,也不喜欢给别人提意见。但是真的有人问我这个问题,我就勉强回答一下。先引用王尔德的一句名言,别人给你一个好的建议,你最好的方法是把这个建议再给别人,好建议对自己是没用的。一个经常问我的问题是:学编程最好学哪个语言?

这个是没有标准答案的,主要看你想做什么?如果你想开发苹果手机上的软件,那就学swift,如果你想学Android的软件开发,那就学kotlin。如果你是计算机专业的大学生,那就选一门C,然后再C++,然后再Java,什么难学就学什么,这是根本。C语言一定要会,那就是你的枪杆子。只要你学会了C/C++和Java,再学其它的编程语言,速度要快的多。如果你是读大学,有4年的时间,学C语言,比学其它的语言都要好。

如果你是随便学学,这个世界,就怕随便。我只能随便建议你,那就随便选个语言。因为你没有目标,只是随便看看,那肯定是学不会的,那就随便学学,反正也学不会,又何必这么在意学哪个语言呢?学会C语言和学会PHP语言,可能有巨大的差别,但是学不会C语言和学不会PHP,效果是一样的,反正都不会。

好,这一期就到这里,忽软忽硬。

5 1 投票
文章评分
订阅评论
提醒
6 评论
最久
最新 最赞
内联反馈
查看所有评论
懒懒龙
12 天 前

赞栋哥又挖一大坑,不过《史记》还更么?

菜皮菜皮
12 天 前

栋哥你说现今许多计算机相关专业或从业人员对系统和底层知识不如以前了解,是否跟现在行业发展越来越细分,封装的越来越抽象有关系?
各种开箱即用的服务或是虚拟化产品在提升效率的同时某种程度上确实会屏蔽掉底层细节。
引用一段之前看到的段子:

教授们发现今天越来越多的年轻人无法理解计算机及操作系统的基本工作原理。目录、文件夹甚至是文件等概念,似乎让在智能手机前长大的一代人感到迷茫而困惑。他们不知道什么叫存储或者怎么操作存储功能。对这一代人来说,“东西”就是“存上了”,不需要别的废话。

电脑爱好者
12 天 前

请问一下之前的讲日本科技的故事什么时候更新?

thewq
11 天 前

爱了

6
0
希望看到您的想法,请发表评论。x
()
x