导读
有人的地方就有江湖,有江湖就有门派。计算机编程语言经过70多年发展,种类众多,形成了大大小小不同的门派。这些门派相互之间最大的乐趣之一就是互黑攻击。
有人的地方就有江湖,有江湖就有门派。计算机编程语言经过70多年发展,种类众多,形成了大大小小不同的门派。这些门派相互之间最大的乐趣之一就是互黑攻击。有一个笑话:程序猿听完就在群里发了一句:PHP是最好的编程语言!程序猿:今天不行,我一定要说服他们,PHP是最好的语言! 要想让程序员们群情激昂最简单的办法就是讨论哪门语言最好,一定能引发各种无下限的互黑。至于是怎么互黑的呢?在知乎上有篇文章:你正在使用的编程语言本身有什么缺陷?- 极客的回答 https://www.zhihu.com/question/266144672/answer/329863232。这是语言互黑的集大成者,还有人根据这篇文章画出了漫画《煮酒论语言》(未找到原始出处)。但是这篇文章就像是编程语言的《春秋》一样,充满了微言大义,对于初学者或者接触其它语言较少的读者来说有些晦涩,为了让大家明白这其中的黑点,我给加上了注释。
以上是过场,下面正式开黑:
1. C语言,万言之父。C语言被许多后续语言效法,包括C++、Java、C#等。但C语言不是最早的语言,它是1972年由贝尔实验室丹尼斯·里奇(Dennis Ritchie)从B语言改进而来。B语言是1969年由贝尔实验室肯·汤普逊(Ken Thompson,他还是Unix操作系统之父)从BCPL语言改进而来。BCPL是1967年由剑桥大学马丁·理察德(Martin Richards)在CPL语言基础上简化而来(前面加的B就是Basic)。CPL是剑桥大学于1963年基于ALGOL 60语言进行的改进。ALGOL最早是1958年ACM小组(美国计算机协会)和GAMM(联邦德国应用数学和力学协会)共同设计的一种通用的与计算机无关的算法语言,分为ALGOL 58、ALGOL 60和ALGOL 68等多个版本。ALGOL是对Fortran语言的继承与发展。Fortran最早是1956年IBM公司约翰·巴克斯(John Warner Backus)为IBM 704计算机开发的科学计算语言,是世界上第一个被正式推广使用的高级语言。在这之前还有1949年由ENIAC计算机设计者之一的约翰·莫奇利(John Mauchly)为BINAC计算机发明的Short Code语言,以及1945年德国工程师康拉德·祖思(Konrad Zuse)为祖思计算机发明的历史上第一款高级编程语言Plankalkül(Plankalkül在德语中是“Plan Calculus”(计划计算)的意思)。但Plankalkül直到1972年才为世人知晓,因此高级语言真正的源头应该是莫奇利的Short Code语言。
2. 贴近底层,运行高效。C语言允许对硬件内存地址进行直接读写,以此可以实现汇编语言的主要功能,并可直接操作硬件。C语言不但具备高级语言所具有的良好特性,又包含了许多低级语言的优势,故在系统软件编程领域有着广泛的应用。与其它高级语言相比,C语言编译以后产生的机器代码数量少,故通常应用于对代码质量和执行效率要求较高的嵌入式系统程序的编写。 3. 面向过程。面向过程(Procedure Oriented)是一种以过程为中心的编程思想。就是分析出解决问题所需要的步骤,然后用函数把这些步骤逐个实现,使用的时候再依次调用函数。面向过程是程序算法结构的基础。
4. 继承大统,面向对象。C++语言是由贝尔实验室本贾尼·斯特劳施特鲁普(Bjarne Stroustrup)于1979年开始在C语言的基础上做面向对象的改进而成,最初的名称为“带类的C”(C with classes),1983年该语言被正式命名为C++。面向对象(Object Oriented)是一种以对象为中心的编程思想。就是分析出解决问题所需要的参与者(即对象),再根据解决问题的需要分别调用各个参与者拥有的函数。面向对象把程序中有关联的数据和函数组织成为一个整体,使其具备封装、继承、多态三大特性,从而大大提高了代码的扩展性与可维护性。
5. 不能反射。反射是指程序在运行时动态获取对象属性与方法的一种机制,即编译器需要将类型信息(属性类型与偏移地址以及成员函数的地址等信息)编译到程序文件中,当程序运行时将这些信息加载到内存中去,做到运行时只根据对象的地址或引用就可以获取到对象的类型信息,从而利用这些信息达到修改或重建对象的目标。在C++中要实现类似Java等语言的反射机制需要另外写代码保存类型相关信息,然后在运行时使用。后来C++引入了typeid运算符,可以在运行时获取类型相关信息,说明C++在编译时是会保存类型相关信息的,只是C++标准要求保存的运行时类型信息不足以支撑类似Java的反射机制。反射机制在不同应用环境下利弊不一,因此一直以来,C++都未能支持反射机制。
6. 容易出错,难以移植。C++的指针是一个非常灵活的机制,但因为其可以绕过类型检查,对于经验不足的程序员非常容易出错。因此有人称指针是C++的灵魂,又有人称其为魔鬼。C++多用于底层开发,自带标准库资源较少,进行跨平台移植时因为代码与原平台关联性较强而需要进行大量调整,同时没有一个被广泛接受的、易用的跨平台构建工具。
1. 完全OO。Java是在1992年Sun公司Green项目小组针对嵌入式产品市场,基于C++简化与改进而成的语言,最初名为Oak。后在1995年改为应用于网页前端,并在注册商标时改名Java。它是一种完全面向对象的语言,它所实现的一切都是对象,包括基本类型、字符串等。虽然Java的基本类型可以用多种运算符进行操作,但这只是一种方便使用的简记法,JVM(Java虚拟机)在创建基础类型时本质都是创建对象。
2. 一次编写,到处运行。Java是一种跨平台的语言,其思路则是用通用平台代替底层的操作系统平台,编程时只使用通用平台的API,程序运行的时候是处在通用平台的环境中,并将对通用平台的API翻译成对底层操作系统的调用,这种运行过程被称为“解释运行”。因为Java程序调用的是通用平台的资源,与底层无关,因此可以实现“一次编写,到处运行”。 3. 泛型太差,历史遗留,强制掰正。泛型的本质是把类型参数化,也就是说泛型可以使类型也成为一个可变的参数,所有属于这个参数类型的对象是类型一致的,而这个类型的参数可以在编程时再进行指定。Java最初没有泛型机制,为了添加泛型采用了“擦除法”,也就是只在编译时进行类型检查,在运行时将泛型参数类型全部转换为Object,这会造成一些类型转换的困扰。
4. 假跨平台。C#是2000年由微软公司发布的一种由C和C++衍生出来的语言。C#基于.net平台资源开发,不直接依赖操作系统,本质上可以跨平台,但.net平台在其它操作系统上实际没有受到什么支持,微软也没有主动提供.net平台的其它操作系统版本,因此其跨平台成了一句口号。
1. Node加持。Node.js就是运行在服务端的JavaScript,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能很好。如果你是一个前端程序员,没学过PHP、Python或Ruby等动态编程语言,如果想创建自己的服务,那么Node.js是一个非常好的选择。
2. 七日怀胎,一朝分娩。1995年,网景公司在确定网页脚本语言开发需求时,受Java的影响很大,要求新语言必须“看上去与Java足够相似”。而JavaScript的发明者布兰登·艾奇(Brendan Eich)对Java一点兴趣也没有,为了应付公司安排的任务,他只用10天时间就把Javascript设计出来了。
3. 语法混乱,超脱六界,集百家之众短。JavaScript由于设计时间太短,语言的一些细节考虑得不够严谨,导致后来很长一段时间,Javascript写出来的程序混乱不堪。JavaScript设计思路是:借鉴C语言的基本语法;借鉴Java语言的数据类型和内存管理;借鉴Scheme语言,将函数提升到"第一等级"(first class)的地位;借鉴Self语言,使用基于原型(prototype)的继承机制。所以,JavaScript语言实际上是一种混合语言,好听点是集众家大成之物,难听点就是临时拼凑的语言,拥有各种奇葩的语法和结构。
4. 还能结合C++。Python是在1991年由吉多·范罗苏姆(Guido van Rossum)在荷兰国家数学和计算机科学研究所设计出来的。Python是ABC语言的一种继承。ABC是由吉多参加设计的一种教学语言。ABC语言并没有成功,吉多认为这是因为其非开放造成的,所以他在设计Python时特别注意开放性。Python是全球全认的“胶水语言”,拥有强大的第三方库,可以将其它语言制作的模块轻松地连接到一起。
5. 万恶GIL。GIL(Global Interpreter Lock,全局解释器锁)是Python语言解释器用于同步线程的一种机制,它使得任何时刻仅有一个线程在执行。崇尚优美、清晰、简单的吉多·范罗苏姆,根据单核CPU时代的条件,在解释器层面实现了一把全局互斥锁来保护Python对象,从而提高单核CPU的使用率,这种做法在当时是非常有效的。但是随着多核CPU时代的到来,高效地利用CPU核心的有效方法就是使用并行性,多线程是充分实现并行的好方法,但是GIL却阻碍了对多核CPU的利用。
6. 二三难选。Python是不向下兼容的,版本3对语法有一些改动,导致部分用版本2编写的代码无法在版本3环境中运行。这使得习惯了版本2语法的部分程序员,面对升级到版本3的选择会感觉很痛苦。
7. 自带游标卡尺。Python是通过缩进来区分代码块的,而其它语言使用大括号或者别的符号来区分。而且其它语言,缩进仅仅为了提高可读性,Python如果前后缩进不一致或者该缩进的地方没有缩进(如if语句的下一行),将无法通过编译。查看已完成的Python代码(特别是打印成书的代码)时,为了明确有几层代码块,需要靠缩进量进行判断。如果代码逻辑复杂层次比较多(或者看书遇上翻页)时,就需要用游标卡尺测量缩进量才知道了。
1. 不搞VM,直接编译。Go语言是由谷歌公司的罗伯特·格瑞史莫(Robert Griesemer)、罗勃·派克(Rob Pike)及肯·汤普逊(Ken Thompson,这位大神前面出现过)等开发,于2009年11月正式推出。Go的语法接近C语言,设计目标是简化并代替日渐庞大的C++,成为谷歌后台开发的新工具,因此它没有使用虚拟机,而是直接编译成机器代码,以贴近底层。
2. 约束BT,Bug不少。Go语言有一些匪夷所思的约束,如:不允许左大括号另起一行;代码行尾的分号是可以省略的,但是编译时会强行添加了行尾的分号,有时会造成错误;if语句的条件表达式可以省掉小括号,以使代码简洁,却不能省掉代码块的大括号,使代码简洁大打折扣;Go编译器不允许存在被未被使用的变量和多余的import,如果存在,必然导致编译错误……此外,Go语言的一些机制也使得产生Bug的机会大增:垃圾回收器(GC)不完善,会导致整个进程不可预知的间歇性停顿;创建对象的方式太多让人选择困难;实现接口不需要明确声明……
3. Pascal,VB,delphi。Pascal语言是由瑞士尼古拉斯·沃斯(Niklaus Wirth)教授在1971年设计并创立的,它是是第一个结构化编程语言,它的名字是为了纪念第一台机械计算器的发明人法国数学家布莱士·帕斯卡(Blaise Pascal,就是那个物理的压强单位帕斯卡)。delphi是一个集成开发环境(IDE),使用的语言是在Pascal基础上添加面向对象特性改进而成的Object Pascal。VB即Visual Basic,是微软开发的一种通用的基于对象的程序设计语言,VB拥有图形用户界面(GUI)和快速应用程序开发(RAD)系统,用于高效生成类型安全和面向对象的应用程序。VB源自于BASIC语言,BASIC(Beginners' All-purpose Symbolic Instruction Code,初学者通用符号指令代码),是一种设计给初学者使用的程序设计语言。BASIC是由达特茅斯学院院长、匈牙利人约翰·凯梅尼(John G. Kemeny)与数学系教师托马斯·卡茨(Thomas E. Kurtz)共同研制,于1964年正式发布。微软起家就是1975年比尔·盖茨为微型计算机Altair 8800编写的BASIC编译器。VB和delphi都曾经辉煌过,但一般用于小型项目开发,而且现在实际开发中已经不流行了。Pascal因为其语言的严谨性常用于教学,许多人的启蒙语言是它。BASIC语言因其简单,被许多应用软件用于扩展编程,产生了许多脚本变体。
1. 小学生能学会。PHP是丹麦裔加拿大程序员拉斯马斯·勒德尔夫(Rasmus Lerdorf)于1994创建的一种通用开源脚本语言,PHP原始名称为Personal Home Page Tools(个人主页工具),现已经正式更名为 "PHP: Hypertext Preprocessor"(超文本预处理器)。PHP语法吸收了C、Java和Perl的特点,利于学习,使用广泛,主要适用于Web开发领域。对初学者来说简单易学,其在web开发中的优势也让他们能马上上手写点东西,容易产生学会的错觉。2. 一种语言,千种写法。PHP的来源之一是Perl。Perl语言是1986年由拉里·沃尔(Larry Wall)设计的文字分析报告语言,用于Unix环境下的编程。Perl的设计思想是:不只一种方法做一件事(There's More Than One Way To Do It),而前面提到的Python的设计思想恰恰相反,是:应当有一种——并且最好只有一种——明确的方法做一件事(There should be one -- and preferably only one -- obvious way to do it)。因此Python发明者吉多被称为“世界上最仁慈的独裁者”。而Perl及其继承者PHP因为过于灵活,导致各种代码风格迥异,被戏称为write-only,即写没问题,读起来就不一定了。3. 维护它是一种有趣的挑战,重构它是一种有趣的冒险。PHP最初设计很不专业。尽管拉斯马斯是个很优秀的程序员,但是语言设计方面不是他所专长,而且一开始他根本没有打算做个语言,而只是给自己个人使用的简单工具集。这导致从设计到实现都有很多临时性的举措:奇怪的大小写设定;函数命名不一致;混乱的参数顺序,导致完全记不住一个函数的用法,每次需要查手册或借助IDE……这些问题都源于未经严格设计。PHP的后续开发也缺乏语言设计专家的参与。一些借鉴其它编程语言的新特性虽然总体上可用,但是存在微妙的语义问题或实现限制。一些设计错误并没有被修复,反而被延续和扩大。再加上PHP学习门槛低、使用者群体庞大,导致代码水平良莠不齐。两种因素相加,无论是维护自己写的代码还是在团队中维护别人写的代码,都显得颇有挑战性。
4. 今天下英雄,唯PHP。PHP语言本身槽点很多,并且因为PHP开发者众多,讨论其缺陷非常容易引发大型论战。而在PHP官方文档中有一段话:PHP is the best language for web programming, but what about other languages?( PHP是web编程最好的语言,而其它语言是怎样的呢?),之后还出现了更激进的言论:Because PHP is the best language ever, ever. It's fast, very powerful, and free(因为PHP是有史以来最好的语言,没有之一。它快速,非常强大,而且免费)。从这两句话就衍生出了语言圈中的一个非常出名的梗“PHP是最好的编程语言”,这成为了对PHP本身最大的戏谑。而因为PHP与“拍黄片”的拼音缩写相同,苍老师也就成了PHP的形象代言。
除了上面的经典文章之外,还有一些有名的黑语言的漫画与段子。比如:
HTML(Hyper Text Markup Language,超文本标记语言)是由Web的发明者 蒂姆·伯纳斯·李(Tim Berners-Lee)和同事丹尼尔·康诺利(Daniel W. Connolly)于1990年创立的一种格式标记语言,网页通过它的标记能明确内容显示时的排版与格式。但因为它标记内容后不能改变(不包括GIF这种本身能变化的内容)且没有交互性,它不能称为编程语言。如果要增加网页动态性与交互性,前端需要与Javascript这类脚本语言结合,后端需要与PHP、JSP、ASP等语言结合。
网页前端现在已经聚集了大量的扩展技术,前端开发人员需要学习的知识量已经让人吃不消了。
Java程序运行在虚拟机上,有一段时间因为虚拟机的运行效率低占用CPU时间长,会导致机器发热,这也成了它的一个黑点。
Perl——唯一一种在被RSA加密之前与之后一个样的语言。主要是嘲笑Perl把键盘数字键上面的所有符号都用了,看起来和乱码差不多。
问:为什么Java开发者要戴眼镜?
答:因为他们不会C#(C Sharp同See Sharp,看得清楚)。
因为Python近年来大火,Python程序员成了各开发公司大力招募的对象。Python之父吉多因为其个人介绍上的一句Guido van Rossum is a Dutch computer programmer who is best known as the author of the Python programming language.(吉多·范罗苏姆是一位荷兰计算机程序员,作为Python编程语言的作者而广为人知。这里还可以理解为“作为《Python编程语言》一书的作者”)而收到一封邀请入职的邮件。
以上都是一些关于语言的黑点与槽点的段子与漫画。语言之间的互黑是编程语言圈的一种有趣的文化,有助于大家放松心情,也有助各语言之间相互促进与发展。其实越是被黑得多的语言,其使用往往越广泛,从而也就越成功。
背景简介:本文作者陶卓彬,毕业于解放军理工大学,曾在军队技术部门从事软件开发十余年,并多次获得军队科技进步奖。现在北京某大学校企从事教育开发工作。长期关注互联网、软件领域课题。文章于2020年6月20日发表于微信公众号 跟陶叔学编程(【轻松一刻】那些关于编程语言的互黑(注释版)),风云之声获授权转载。