编程语言考古,2022年笔记迁移
高级语言,之所以被称为高级语言,是因为它们接近人类语言,易于理解。
关于编程语言的世代,目前支持比较广泛的一种说法,是:
第一代:机器语言,20世纪50年代中期以前
第二代:汇编语言
第三代:高级语言,从20世纪60年代开始。前两代语言与人类的思维表达方式不符,使用很不方便,于是设计出了符合人类思维和语言习惯的编程语言,即高级语言。
第四代:面向问题的语言,现代编程。是传统软件工业界为了“范式开发”而设计出来的语言,可以理解成是商业需要,它是在三代语言基础上的加强,四代语言完成相同作业所需的代码行数、较三代语言要少很多。因此,四代语言又称为面向问题的语言和高生产率语言。
第五代:智能化语言,也称为自然语言。为人工智能领域而设计,帮助人们编写推理、演绎程序。
四代语言(Fourth-Generation Language, 以下简称4GL),最早是在80年代初期出现在软件厂商的广告和产品介绍中的,这些厂商的4GL从形式和功能上看,差别都很大,但是由于这一类语言具有面向问题等特点,可以成数量级的提高软件生产率,缩短软件开发周期,因此赢得了很多用户。于是,1985年,美国召开了全国性的4GL研讨会,也正是在这前后,许多著名的计算机科学家对4GL展开了全面的研究,使得4GL真正意义上的进入了计算机科学的研究范畴。
为什么说4GL是面向问题的呢,是因为4GL其实是实现了某些标准处理过程的自动生成,用户只需要说明要做什么,要解决什么问题,软件会自动处理、安排具体的执行步骤。
另外,4GL主要面向基于数据库应用的领域,相比3GL,自由度差很多,毕竟抽象程度更高。
感觉四代语言,其实就是工业软件语言,我们常用的MATLAB,就被划为四代语言。但是其实编程语言的世代划分很有争议,同一门语言,有支持是3GL、也有支持是4GL的,众说纷纭。所以关于世代的划分,简单看看就可以,没必要过于探究。
SQL,是目前为止,公认的最成功的的第四代语言。
世代不代表高世代的语言就更好,低世代的语言就差,比如说java是3GL,MATLAB是4GL,二者孰优孰劣?
程序设计语言可以分为三大类:机器语言、汇编语言和高级语言。
最早出现的是机器语言。
机器语言,第一代计算机语言
计算机可以处理二进制,而二进制才是处理器的“母语”,这叫做机器语言或者机器码。
在计算机早期阶段,必须使用机器码来写程序。具体过程是这样的:
下面是一段典型的机器语言代码。
我们需要知道所有的机器指令,且记住所有机器指令对应的二进制代码,才能设计好程序。这个过程是很繁琐的。而且每条机器语言指令只能执行一个非常小的任务,要想执行一个大的任务的话,代码量是无法想象的。
早期的程序设计均使用机器语言,程序员们将用0, 1数字编成的程序代码打在纸带或卡片上,1打孔,0不打孔,再将程序通过纸带机或卡片机输入计算机,进行运算。
下面是机器语言指令的部分举例:
//指令部分范例
0000 //代表加载(LOAD)
0001 //代表储存(SET)
...
//暂存器部分范例
0000 //代表暂存器A
0001 //代表暂存器B
...
//内存部分范例
000000000000 //代表位址为0的内存
000000000001 //代表位址为1的内存
000000001000 //代表位址为16的内存
...
//集成范例
0000, 0000, 000000001000 //代表LOAD A, 16
0000, 0001, 000000000001 //代表LOAD B, 1
汇编语言(Assembly Language),第二代计算机语言
靠机器语言实在是太麻烦了,所以在1940年-1950年,开发者们开发了汇编语言,它使用了大量的助记符来代替二进制指令:
例如用ADD表示加、SUB表示减、JMP表示程序跳转等,这种指令助记符号的语言就是汇编语言,又称符号语言。
mov eax, 3 //将3存入EAX寄存器(3是一个立即数)。
mov bx, ax //将AX的值存入到BX寄存器。
//ADD指令用来进行整形数据的相加。
add eax, 4 //eax = eax + 4
add al, ah //al = al + ah
//SUB指令用来进行整形数据的相减。
sub bx, 10 //bx = bx - 10
sub ebx, edi //ebx = ebx - edi
//INC和DEC指令将值加1或减1。因为1是一个暗指的操作数,INC和DEC的机器代码比等价的ADD和SUB指令要少。
inc ecx //ecx++
dec dl //dl--
例如,计算A=15+10的汇编语言程序如下:
MoV A,15:把15放入累加器A中
ADD A,10:10与累加器A中的值相加,结果仍放入A中
HLT:结束,停机
汇编语言将开发者从那些繁琐晦涩且难记的二进制指令中解脱了出来,一定程度上解决了机器语言难读难改的缺点。
计算机并不认识助记符,它只认识二进制码,所以先辈们开发了“汇编器”,用来将文字指令转换成二进制机器码。这样子,程序员可以专心文字编程,而不用管底层细节。
直到现在,汇编语言仍然在编程语言市场上占有一席之地,只不过这个席越来越小了。如操作工业机器人、单片机编程和某些计算机病毒的编写等。
该语言还依赖于具体型号的机器,不同的计算机在指令长度、寻址方式、寄存器数目、指令表示等方面都不一样,这样使得汇编程序不仅通用性较差,而且可读性也差。
高级语言,第三代计算机语言
也是目前市场的主流语言。
高级语言,是被高度封装了的编程语言。它以人类的日常语言为基础,使用一般人易于接受的文字来表示,使得程序员编写程序更容易,可读性更高。
当然,由于早期计算机产业的发展主要在美国,因此一般的高级语言都以英语为蓝本。
1950年之后,集万千宠爱于一身的高级编程语言诞生了。
Fortran (1955),名称取自"FORmula TRANslator"(公式翻译器),由美国计算机科学家约翰·巴科斯等人所发明;是世界上第一个被正式采用并流传至今的高级编程语言。从1956年正式使用,直到2022年已有66年历史,且经久不衰,至今仍是数值计算领域所使用的的主要语言。
同期被提出的还有:
这三大语言所派生出来的语言,直到今日仍旧广泛的被采用。
用人类能够读懂的字符与计算机沟通交流
优势:学习难度大大降低 编程效率大大提高
劣势:计算机无法直接识别 执行速度相对较慢
接下来至今,就是第三代计算机语言-高级编程语言发展成熟的历程了。
1967-1978年,确立了编程语言的基础范型。
大多数现在所使用的主要语言范型,都是在这段期间中发明的。
这些编程语言,各自演变出了自己的家族分支,现今大多数现代编程语言,都可以追溯它们中的一个或者多个作为祖先。
C语言的诞生历程:
1980年代,增强、模块、性能。
1980年代,各大始祖级别编程语言开始壮大自身,愈发成熟。同时也提出了很多新的编程语言。
比如说,
C++合并了面向对象以及系统程序设计。
美国政府标准化一种名为Ada的系统编程语言并提供给国防承包商使用;
日本以及其他地方运用了大量的资金对采用逻辑编程语言结构的第五代语言进行研究;
函数编程语言社区则把焦点转移到标准化ML及Lisp身上
总的来说,这一阶段,大家的活动都不是开发新的范型,而是将上个时代的构想进一步发展壮大。
不过,这个阶段,在语言设计上有个重大的新趋势,就是研究运用模块或大型组织化的程序单元来进行大型系统的开发。
在这段期间被开发出来的重要语言包括有:
1990年代:互联网高速发展的时代。
90年代,整体来说,同样没有什么大的范式创新,基本是以前构想的组合或者优化。这段时间考虑的主要是如何提升程序员的生产力。这一阶段,许多"快速应用程序开发" (RAD) 语言也应运而生,这些语言大多都有相应的集成开发环境、垃圾回收等机制,且大多是先前语言的派生语言。这类型的语言也大多是面向对象的编程语言。
在这一阶段被开发出来的重要语言包括:
1995年,Netscape公司的Brendan Eich,在网景导航者浏览器上研发出了JavaScript
。最开始取名LiveScript,因为Netscape与Sun合作,Netscape管理层希望它外观看起来像Java,因此取名为JavaScript。但其实js跟java一点儿关系没有。
可以看到,有很多熟悉的面孔,python、java、js、php等。
2000年后,编程语言持续进一步发展,趋势也有很多,比如说更重视分布式及移动式应用等。
这段时间被开发出来的重要语言有:
Swift是苹果于2014年开发者大会上正式发布的一种开发语言,可以于objective-C共同运行于macOS和IOS平台,用来搭建基于苹果生态的应用程序。并于2015年12月正式开发全部源代码。
值得一提的是,2014年6月3日,Swift被发布,2014年6月4日,github上就发起了Swift中文版翻译的项目,该项目在不到一周的时间就获得了1067个star,并于6月12日正式发布了第一版《Swift中文版》。截止目前,这个项目的star数已经突破了2w,218人贡献过翻译。值得一提的是,该项目的发起人是北航的一名大三学生。
Kotlin是由JetBrains公司开发,是一门面向JVM的新语言,于2011年7月正式立项,于2016年2月正式发布第一个稳定版本。据说Kotlin希望这个新语言能够推动IntelliJ IDEA的销售。
在Google I/O 2017大会上,Google宣布将Kotlin作为android官方支持开发语言,为其在Android上提供一等支持。
第五代语言就是自然语言,又被称为知识库语言或者人工智能语言,目标是最接近日常生活所用语言的程序语言。真正意义上的第五代语言尚未出现,LISP和PROLOG号称第五代语言,其实还远远不能达到自然语言的要求。
所以这些年编程语言的发展历程,实际上是学习门槛不断降低的过程,但这个过程理论上对计算机是不友好的。
高级语言所编写的程序不能直接被计算机识别,必须经过转换才能被执行。
按照转换方式的不同,高级语言可以分为解释型和编译型。
什么是编译型语言?
编译型语言在被执行之前,需要通过编译器,将源代码编译成一个可执行程序。一次编译后即可重复执行。
代表语言有:C、C++、Golang等。
编译型语言最大的问题是不能跨平台,能跨平台就怪了,因为不同操作系统对可执行文件的要求根本不同,无法兼容,在linux平台上编译出的可执行程序,在windows上会无法运行。
其次,编译型语言,源代码也不能跨平台,不同操作系统下的函数、变量、api等也可能也会有不同。
什么是解释型语言?
解释型语言是使用解释器,一行一行代码解释执行。它不会生成可执行程序,每次执行都需要重新解释。
代表语言有:JavaScript、Python、PHP、Shell、java等。
解释型语言的跨平台性要好,他可以通过解释器,将相同的源代码解释成不同平台下的机器码。
缺点也很明显,要一行一行,边解释边执行,效率很低。
说到这里就不得不提一下java了,关于java是解释型语言还是编译型语言,其实这一点是很有争议的,有很多人支持java是编译型语言,也有很多人支持它是解释型语言,或者是干脆认为它是半编译半解释型语言。
java是一种比较有意思的语言,严格来讲,它是一种先编译后解释的语言。Java首先是通过编译器编译成字节码文件,然后在运行时通过解释器给解释成机器语言来执行。
python其实也算是先编译后解释的,只不过相比java要弱化一些。
在我们初学python的时候,见得最多的一句话就是:python是一门解释型语言。其实严格来讲,这么说基本是正确的,但是不完全正确。
在辩证分析这个问题之前,我们需要首先明确两个概念:PyCodeObject和pyc文件。
PyCodeObject,是Python编译器编译后的字节码,这个字节码是位于内存中的。
当python程序运行时,会发生什么呢?
当python程序运行时,编译的结果是保存在位于内存中的PyCodeObject中,当Python程序结束运行时,Python解释器会将PyCodeObject写回到磁盘上的pyc文件中。
当这个程序第二次运行时,程序首先会在硬盘中寻找pyc文件,如果找到,就直接载入,否则就重复上面的过程,重新编译。
所以我们应该这样来定位PyCodeObject和pyc文件,我们说pyc文件其实是PyCodeObject的一种持久化保存方式,即字节码,这点与JAVA是一样的。
因此,.pyc文件是由.py文件经过编译后生成的字节码文件,其加载速度相对于之前的.py文件有所提高,而且还可以实现源码隐藏,以及一定程度上的反编译。比如,Python3.3编译生成的.pyc文件,Python3.4就别想着去运行啦!
但是需要注意的是,python解释器并不会为所有的py文件都生成pyc,而是只为我们会重用的模块来生成pyc。比如说,如果一个py文件,没有在其他文件中被import过,那就被视为一次性文件,不会被生成pyc。
pyc文件是有过期时间的,每次在载入之前都会先检查一下py文件和pyc文件保存的最后修改日期,如果不一致则重新生成一份pyc文件。
这样做主要是为了提高效率、性能。毕竟,每次都重新解释太慢了。
关于编译器和解释器,在最初的时候会有比较明晰的界限。因为解释型语言很明显是读入一条语句或者表达式就执行一条,而编译器是会完成全文编译才产出可执行程序的。
但随着编译器技术发展,这两者之间的界限越来越模糊。编译型语言也可以拥有解释器,解释型语言也需要编译这个步骤来进行分析和提速。所以现在也不能再纯粹的把语言分为编译型和解释型这两种。
因此不必纠结于概念,应该直接探求其实质,否则会纠结在编译和解释之间的区别里。
根据编程思想的不同,编程语言可是分为面向过程的结构化设计语言,以及面向对象的设计语言。
面向过程的编程语言。
把构成问题的事务分解成一个个函数。是一种以过程为中心的编程思想,是以什么正在发生为主要目标进行编程。
面向过程语言有:C、Fortran、Pascal等
面向对象的编程语言。
把构成问题的事务分成一个个对象,建立对象的目的不是为了完成一个步骤,而是为了描述某个事物在整个解决问题的步骤中的行为。
面向对象的编程语言,最大的三个特征:封装、继承和多态,最重要的一个特征就是类。
面向对象的语言有:C++、C#、java、delphi、Python、Simula等。
面向对象的编程方式使得每一个类只做一件事。面向过程会让一个类越来越全能,就像一个管家一样做了所有的事。
举一个简单的例子来说明面向过程和面向对象的区别。
我们现在要把大象放进冰箱。
面向过程会将这个问题分解为三步:
转换为伪代码,应该是这样的:
// 打开冰箱函数
bool openRefrigerator(){........}
// 放进大象函数
bool pushElephant(){........}
// 关闭冰箱函数
bool closeRefrigerator(){......}
//主函数
int main(){
//........
if(openRefrigerator()) // 判断是否可以打开冰箱
{
pushElephant(); // 放进大象
closeRefrigerator(); // 关闭冰箱
}
//.......
}
如果是面向对象编程的话,会怎么做呢?
面向对象将一个事物描述为一个对象,这个对象包括各种属性和方法。
比如说把大象放进冰箱这个例子,大象和冰箱分别是一个对象,冰箱有长宽高和温度等属性、还有打开、关闭、存储等属性。大象也有自己的体重、高度、体积等属性,有自己的吃饭、走路、睡觉等方法。
所以说面向对象在分解“大象放进冰箱”这个例子的时候,是:
转换成伪代码:
class Elephant
{
private :
int length; // 长
int weight; // 重量
public :
// 吃
bool eat(){......}
};
class Refrigerator
{
private :
int length; // 长
int width; // 宽
int height; // 高
public :
// 打开冰箱
bool openRefrigerator(){........}
// 放进大象
bool pushElephant(Elephant elephant){........}
// 关闭冰箱
bool closeRefrigerator(){........}
};
int main()
{
Refrigerator ref; // ref 冰箱对象
Elephant ele; // ele 大象对象
if(ref.openRefrigerator()) // 打开冰箱
{
ref.pushElephant(ele); // 放进大象
ref.closeRefrigerator(); // 关闭冰箱
}
}
面向过程通常采用自上而下的设计方法,而面向对象通常采用自下而上的方法。
TIOBE排行榜,用来反应某个编程语言的热门程度,是根据互联网上有经验的程序员、课程和第三方厂商的数量,并使用搜索引擎(如Google、Bing、Yahoo!)以及Wikipedia、Amazon、YouTube和Baidu(百度)等25个引擎统计出的排名数据。
TIOBE目前监控了足足270多种编程语言,当一种新的编程语言通过了TIOBE的检验标准之后,就会被纳入监控。
至于检验标准,有很多,核心有三个:
TIOBE排行榜只能用来反应某个编程语言的热门程度,并不能说明一门编程语言好不好,或者一门语言编写的代码量之类的。
排行榜每月初更新一次,依据全世界范围,其结果目前是作为当前业内程序开发语言的流行使用程度的有效指标。每次都会列出Top100。
该排行榜可以用来检阅开发者的编程技能能否跟上趋势,或是否有必要作出战略改变,以及什么编程语言是应该及时掌握的,因为它毕竟反映了世界范围内开发语言的一个走势。
历年年度最佳语言:
2003年:C++
2004年:PHP
2005年:Java
2006年:Ruby
2007年:Python
2008年:C
2009年:Go
2010年:Python
2011年:Objective-C
2012年:Objective-C
2013年:Transact-SQL
2014年:JavaScript
2015年:Java
2016年:Go
2017年:C
2018年:Python
2019年:C
2020年:Python
2021年:Python
目前使用的25个搜索引擎:
根据这些标准,以下搜索引擎是合格的:
Stack Overflow,最著名的IT技术问答网站,每年也会做一些IT项的调查,包括但不限于最受欢迎的编程语言排行榜。
但是他们调查的样本很少,可信度比Tiobe要差很多。
比如2021年,只有8.3w人参与问卷调查,其中91.67%是男性,5.31%是女性,甚至还有1.6%的人说自己是盲人。不过虽然人少,但是结论都挺有意思。
最受欢迎的编程语言Top15:
JavaScript已经连续九年被评为最流行的编程语言了,因为对于大多数开发人员来说,开发就是web编程。
最常使用的数据库排行:
最受欢迎的IDE开发环境:
最常使用的操作系统:
每门编程语言,喜欢与讨厌的占比,这个图有点大,直接去参考文献21自己看吧。
数据库,喜欢与讨厌占比:
db2公认很讨厌啊。
还附有薪水榜,这个就不介绍了,后期自己看参考文献21吧。
易语言,类似VB,于2000年提出;
要想使用易语言,需要先下载它的开发软件。
使用易语言来打印hello world:
标准输出(“hello world”)
标准输入 ()
今年还看了个新出的玩具型中文语言,叫Qi语言,即气语言。
网站首页很好看,不过据说目前还是停留在将英文编程语言翻译成中文的地步。
看了下文档,还是很有意思的,比如说打印hello world:
系统。打印行(“你好,世界”)
从文字到标点符号,全是中文。
再来一个条件控制的:
如果(假)「
系统。打印行(“不会打印”) // 不会打印
」否则「
系统。打印行(“会打印”)
」
见参考文献4,老外吐槽“世界上最不受欢迎的编程语言”,是他自己搞的一个叫做Hyperlambda的语言,世界上只有一个开发人员实际使用过它。。。
事情的起因是,Google选择将java作为Android的编程语言。
为了达到Android与Java应用程序间的高度兼容,Google复制了Java库中大约20%子例程的11000个声明。通过这个方法,Java程序员更容易将带有Java调用的现有应用程序移植到Android而不必从头开始重写应用程序。
2010年,甲骨文斥资74亿美元收购了Java创始公司sun计算机系统的资产,并随后起诉Google侵犯版权。
java语言是不具有版权的,虽然java是不完全开源,但是毫无疑问,预编写的子例程是具有版权的。那么到子例程的链接声明是不是有版权的呢?
2011年,Oracle要求Google支付高达60亿美元的损害赔偿金。Oracle首席执行官Larry Ellison和Google首席执行官Larry Page被勒令进行谈判以达成和解,但未能达成协议。
2012年,陪审团未能一致确定Google使用37个Java API作为Android API的一部分是否属于合理使用。但是美国加州联邦法院(the Northern District of California)法官依据加州第九巡回上诉法院判例法裁定声明不属于版权保护范围,即Google胜诉。Oracle提出上诉。
2014年,美国上诉法院推翻了Alsup法官的先前裁决,裁定Oracle的37个Java API软件包实际上受版权法保护。上诉法院还就rangeCheck函数和8个反编译的安全文件做出了对Oracle有利的裁定,并要求案子退回到初审法院,进入进一步的诉讼程序。
2014年,Google提交请愿书,要求美国最高法院审核联邦巡回法院的裁决。
2015年,最高法院驳回了Google要求审理此案的请愿书。
2016年,此案被退回初审法院,初审法院采用陪审团意见维持原判,认为Google使用java API是合理使用。
2017年,Oracle再次向美国联邦巡回上诉法院提起上诉。
2018年,巡回区上诉法院再次做出裁决支持Oracle,并要求初审法院裁定损害赔偿金。Google就此诉请最高法院审查该案件,最高法院最终批准受理。
2020年,最高法院判定Google胜诉,法院判决6比2,十年版权之争,就此尘埃落定。
需要提一下的是,Google早就厌烦了这场拉锯战,他们在2017年提出将使用Kotlin作为Android的开发语言。