两万字长文:编程语言大串讲
TL;DR
本文收录在《大道至简,给所有人看的编程书》第 3 章,讲述了编程语言的发展历史,以及各种编程语言的特点。本文是一篇长文,大约两万字,建议在电脑上阅读。
公认的世界上“第一位给计算机写程序的人”叫 Ada lovelace(艾达·洛芙莱斯),她是英国著名诗人乔治·戈登·拜伦(George Gordon Byron)的女儿。她在 1843 年写了一篇论文,公布了世界上第一套算法,建立了循环和子程序概念。当然,当时也没有现代意义上的计算机,她只见过查尔斯·巴贝奇(Charles Babbage)设计的差分机,她写的程序当年也无法运行,只是一套算法和理论。
不过,真有一种编程语言叫 Ada,就是为了纪念 Ada,以她的名字命名的。Ada 语言源于美国军方的一个计划,大约出现在 19 世纪 80 年代,旨在整合美军系统中运行着上百种不同的程序设计语言编写的程序。Ada 最初主要用于军事和航空航天领域,比如美国军方和波音公司。经过几十年发展,Ada 已经成为了一个现代语言,它内建并发、同步语义、消息机制,支持运行时类型检查等。下面是 Ada 版的 Hello World1程序:
with Ada.Text_IO;
procedure My_Hello_World is
begin
Ada.Text_IO.Put_Line ("Hello, World!");
end My_Hello_World;
我们现代使用的计算机统称冯·诺依曼体系结构计算机,是由冯·诺依曼(John von Neumann)设计的。冯·诺依曼是一位数学家,他在 1945 年发表了一篇论文,提出了“存储程序”的概念,这篇论文被认为是计算机科学的开山之作。冯·诺依曼提出了计算机制造的三个基本原则:
- 采用二进制逻辑。
- 程序存储执行。
- 计算机由五个部分组成(运算器、控制器、存储器、输入设备、输出设备)。
最初,人们使用穿孔卡片作为计算机的输入,穿孔卡片的灵感来自于给火车票打孔做标记。最初的编程语言就是机器语言。机器语言就是计算机理解的二进制指令。下面,假设我们制造了一台 4 位的计算机,那么,我们可以用 0000 表示加法,0001 表示减法,0010 表示乘法,0011 表示除法等。这样,我们就可以用 0000 0001 0001 来表示“1+1”。
- 说到这里,有的读者可能会感到困惑。别着急,我们看一下以下表格就明白了(表中 A 和 B 为两个参与运算的数,称为操作数)。
-
简单机器指令表
指令 | 含义 | A | B | 说明 |
---|---|---|---|---|
0000 | 加 | 0001 | 0001 | 1 + 1 |
0001 | 减 | 0001 | 0001 | 1 - 1 |
0010 | 乘 | 0001 | 0001 | 1 × 1 |
0011 | 除 | 0001 | 0001 | 1 ÷ 1 |
以“1 + 1”为例,按照人们直接的理解,应该写成“0001 0000 0001”,即“加数 加号 被加数
”这种格式。但在计算机中,一般使用“指令 操作数A 操作数B
”这样的格式,在本例中即“0000 0001 0001”。至此,你可以理解为我们刚刚制造了一台计算机,并写下了第一个计算“1 + 1”的程序。
上面,简单起见,我们使用了一个 4 位的计算机。这个 4 位就是计算机的字长,也即计算机一次处理指令的二进制位长度。在 DOS 时代的 CPU 一般是 16 位的(286 以前),386 以后的 CPU 是 32 位的,也有了 32 位的 Windows 操作系统。现在,我们常用的 CPU 都是 64 位的。
机器语言很难记忆,因此,后来人们发明了汇编语言(Assembly Language,台湾译为“組合語言”,简写为 asm)。汇编语言其实就是一些机器语言的助记符,比如,我们可以用“ADD 0001 0001”来表示“1 + 1”,通过一个翻译程序,可以将 ADD 翻译成加法指令“0000”。当然,除了一对一的指令助记符外,汇编语言还有一些伪指令,用于描述数据等。
然而,汇编语言还是难于记忆,而且,不同的 CPU 有不同的汇编语言指令集,用汇编语言为一种 CPU 写的程序很难移植到其他 CPU 上。在 19 世纪 50 年代,人们就发明了一些“高级”语言,方便程序员们编写程序。
最有代表性的是 Fortran 语言,约 1955 年。它的名称取自“FORmula TRANslator”(公式翻译器),由约翰·巴科斯(John Backus)等人所发明,是世界上第一个被正式采用并流传至今的高级编程语言,主要用于数学计算。Fortran 是给科学家使用的语言。
LISP 语言,名称取自”LISt Processor”(枚举处理器),由约翰·麦卡锡等人所发明,LISP 是函数式编程语言,也是为人工智能设计的语言。《黑客与画家》的作者 Paul Graham 就是 LISP 的拥趸,他在书中写到他们 Web 服务产品的其中一项核心竞争力就是由于使用了 LISP。现在,经过几十年的发展,LISP 有了众多不同的“方言”,比较著名的有 Scheme、Common Lisp、Clojure 等。其中,Clojure 被设计运行于 Java 虚拟机 JVM 之上,相当于“运行在 Java 虚拟机上的 LISP”。
COBOL 语言(1959 年),名称取自“COmmon Business Oriented Language”(面向商业的通用语言),由被葛丽丝·霍普(Grace Hopper)深刻影响的 Short Range Committee 所发明。COBOL 主要用于银行、航空和政府等关键业务,经过几十年的发展,目前会用 COBOL 的程序员都已老去,许多年轻的程序员却根本没有学过它。然而,目前还有很多使用 COBOL 编写的系统在使用。COBOL 系统主要运行在大型机上,本来就比较小众,再加上都是关键业务,替换 COBOL 的成本太高(主要是万一出了问题没人背锅)。据说著名的云服务厂商亚马逊提出了一个 COBOL 自动转 Java 工具「AWS Mainframe Modernization」,旨在帮助 AWS 客户「尽可能快地」脱离大型机,更好地利用云服务。在人工智能大爆发的 2023 年,IBM 也推出了一款将 COBOL 转换为 Java 的工具——IBM watsonx Code Assistant for Z,旨在 将 COBOL 代码重构为 Java 来实现古董大型机软件的现代化。
1964 年,美国达特茅斯(Dartmouth)学院约翰·凯梅尼(John Kemeny)和托马斯·卡茨(Thomas Kurtz)认为,像 Fortran 那样的语言太过专业,编程非常困难。于是他们简化了 Fortran,并设计出了更适合初学者的 BASIC (Beginner’s All-purpose Symbolic Instruction Code,初学者通用指令代码)语言。BASIC 语言实在是太成功了,几乎所有使用电脑的人都会使用 BASIC 编程。后来,到 70 年代,苹果公司的 Apple I 和 Apple II 电脑甚至连操作系统都没有(Apple I 甚至连机箱都没有,见下图),但是可以运行 BASIC 语言解释程序。
BASIC 语言很简单,也有很多“方言”,比如微软公司的 GW-BASIC、QuickBasic、QBASIC(QuickBasic 的简化片)等。BASIC 语言本质上是一种解释型语言,有的版本也可以直接编译成可执行程序。后来,Windows 出现后,微软推出了 Visual Basic(简称 VB),可以通过拖拽鼠标进行图形界面(GUI)编程,实在是程序员的利器。BASIC 语言也出现在网站(后台)编程语言中,比如微软的 ASP(Active Server Pages,动态服务器页面);在 IE 浏览器中,有 VBScript(与 JavaScript 地位差不多);在 Office 中,有 VBA(Visual Basic for Applications,应用程序的 Visual Basic),有些宏病毒就是用 VBA 写的。后来,微软将 Visual Basic 统一到.NET 框架中,称为 VB.NET,不过,微软在 2017 年宣布不再开发 VB.NET,在 2023 年首先在 Excel 中支持 Python 语言,标志着 BASIC 语言的没落。
1970 年代中后期,Alan Kay 发明了面向对象的编程语言 Smalltalk,在 Smalltalk 中,一切皆对象,大大影响了后续语言的开发。
1970 年,尼古拉斯·沃斯(Niklaus Wirth,1934 年 2 月 15 日 ~ 2024 年 1 月 1 日,在本书写作时听到他去世的消息)非常痴迷于编程语言,他率先提出了结构化程序设计思想并发明了 Pascal 语言。我上大学时(1997 ~ 2001),主流的数据结构书还是用 Pascal 语言描述的。后来 Pascal 在 1995 年变成了面向对象的 Object Pascal 和 Delphi,成为与 VB 类似的 GUI 编程语言。
1971 年,肯·汤普森(Ken Thompson)发布了第一个 UNIX Shell —— Thompson Shell。但是,脚本用户所能做的存在严重限制,这意味着严重制约了自动化以及整个 IT 运营领域。六年后的 1977 年,Stephen Bourne 发布了 Bourne Shell,旨在解决 Thompson Shell 中的脚本限制。1987 年,Brian Fox 创造了 Bourne-Again Shell,就是我们所熟悉的bash
,功能和易用性大大超过了 Bourne Shell。使用 Shell 语法编写的自动化命令脚本称为 Shell 脚本。Shell 脚本是一种解释型语言,由 Shell 解释运行,因此运行有些慢。除了 Bourne Shell 外,后来还出现了其他 Shell,比如 C Shell(csh)、Korn Shell(ksh)、Z Shell(zsh)等。其中 C Shell 的语法有些 C 语言的影子,在 BSD 及 Sun 系列的 UNIX 上是默认的 Shell。
1972 年,丹尼斯·里奇与肯·汤普森在贝尔实验室工作期间发明了 C 语言,开启了现代程序语言的革命。C 语言大大提高了编程效率和可移植性,成为了一切语言的基石,至今都是主流的编程语言。除了 C 语言之外,汤普森还和贝尔实验室的同事创造了伟大的 UNIX 操作系统。C 语言是面向过程的编译型语言。时至今日,国际标准化组织发布过几个 C 语言的标准,如 C89、C99、C11、C12、C2x 等,但总体上变化不大。
1972 年,由 Colmerauer、Roussel 及 Kowalski 设计了 Prolog,它是第一个逻辑程序语言。它创建于逻辑学的理论基础之上,最初被运用于自然语言等研究领域。这门语言已几乎被人遗忘,但它对后面的 Erlang 语言影响颇深。
1974 年,Boyce 和 Chamberlin 提出了 SQL 语言,并首先在 IBM 公司研制的关系数据库系统 SystemR 上实现。SQL 的全称是 Structured Query Language,即结构化查询语言语言,它是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统。关系模型是 Edgar Frank (Ted) Codd 在 1970 年发表的一篇论文(A Relational Model of Data for Large Shared Data Banks2,大型共享数据库中的数据关系模型)中提出的。美国国家标准局(ANSI)开始着手制定 SQL 标准,并在 1986 年 10 月公布了最早的 SQL 标准,扩展的标准版本是 1989 年发表的 SQL-89,之后还有 1992 年制定的版本 SQL-92 和 1999 年 ISO 发布的版本 SQL-99。SQL 标准几经修改和完善,其功能更加强大,但目前很多数据库系统只支持 SQL-99 的部分特征,而大部分数据库系统都能支持 1992 年制定的 SQL-92。
1980 年 12 月 10 日,为了集成美军系统运行的上百种语言,提高调试效率,美国国防部决定开发一种新的通用编程语言,命名为 Ada,以纪念 Ada Lovelace。Ada 由 Pascal 及其他语言扩展而来,接近自然语言和数学表达式;其最早针对嵌入式和实时计算设计,至今依然在这些领域广泛使用。1983 年 4 月 11 日,Ada / Ed 翻译器首次执行 Ada 语言验证成功。据称,在 Ada 语言出现后,美国国防部在 1983 年使用的 450 种编程语言,到 1996 年只剩下 37 种了。
SPARK 语言是基于 Ada 的一个子集开发的一种新语言,SPARK 是 SPADE Ada Kernel 的缩写形式。Ada 支持静态检查,可以在编译时检查出大部分问题,致力于打造“安全”的语言和软件。据说 SPARK 和 Rust 一样好,编程更安全。2022 年一则消息称3英伟达在一些项目中用 SPARK 换掉了 C。
1981 年,Brad Cox 是一名研究开发语言生产效能的研究员,为了能让类似 Smalltalk 的面向对象的语言与 C 结合并运行在 UNIX 系统上,它开发了一个叫 Object-Oriented Pre-Compiler(OOPC,面向对象的预编译器)的预编译器,用于将类似 Smalltalk 的语言编译成 C 语言,后来演变成 Objective-C(面向对象的 C)。1986 年乔布斯在 NeXT 电脑公司,当时 NeXT 是 Objective-C 的大用户,后来 Objective-C 被 NeXT 大大改进并与乔布斯一起回到苹果,成了 iOS 和 MacOS/macOS 上的主要编程语言。
1980 年左右,Bjarne Stroustrup 也在 C 语言的基础上引入面向对象的概念,最开始叫“C with Classes”,在 1983 年更名为 C++。C++ 与 C 语言兼容,引入了类、继承、虚函数、函数重载、引用机制、const 关键字以及双斜线的单行注释等,在一定程度上提升了开发效率,但也带来了很多复杂性,编译速度也比 C 更慢。C++ 与 C 运行效率相近。
1986 年,爱立信的 Joe Armstrong、Robert Virding 和 Mike Williams 开发了 Erlang 语言的第一个版本。它最初是爱立信内部的专有语言,后来于 1998 年作为一种开源语言发布。Erlang 是一门函数式编程语言,受 Prolog 和 Smalltalk 影响较大。Erlang 是一门电信级的编程语言,它的主要特点就是分布式、高并发和高容错。Erlang 支持热代码更新(类似于为行驶的车换轮子),理论上编写正确的 Erlang 程序可以永不停机。Erlang 有配套的 OTP 库(Erlang 中的中间件和库的集合),被广泛称为 Erlang/OTP。有一点与 Java 类似的地方就是 Erlang 语言也是运行在一层虚拟机上,称为 BEAM(在 Java 中是 JVM)。Erlang 使用于 Actor Model 并发模型,它的 Process 非常廉价(类似 Go 语言里的协程),Process 之间不共享数据,而是通过邮箱通信,这会带来一些额外的开销,但减少了锁的使用,是高并发、高容错实现的基础。
1987 年,拉里·沃尔发明了 Perl 语言。这是一个脚本语言,有强大的正则表达式功能用于处理字符串模式匹配,常用于自动化脚本和运维场景中。Perl 语言还可以用于设计 Web 网站后端的 CGI 程序。当然,Perl 语言太过强大,语法灵活,但可读性差。大家经常开玩笑说“Perl 脚本的作者在 6 个月后也读不懂自己写的 Perl 代码”。
1988 年,John Ousterhout 在加州大学伯克利分校工作时创建了 Tcl(Tools Command Language)语言。据作者介绍,它最初是由程序员设计自己的语言来扩展电子设计自动化(EDA)软件,更具体地说是完成一些 VLSI 设计工具的“魔法”,这是 John 当时的专业重点。这是一门小众语言,但几乎所有 UNIX 系统上都有它,即使不做电子设计,它也很适合做一些自动化运维应用。时隔 30 多年,TCL 仍然在 IC(集成电路)设计领域有广泛的应用。结合 Tk(Tool Kit),合称 Tcl/Tk,也可以写图形界面的程序。
Haskell 是一种通用的、静态类型的、纯函数式编程语言,诞生于 1990 年。它具有类型推断和惰性求值,为教学、研究和工业应用而设计,开创了许多高级编程语言功能,例如类型类,这些功能支持类型安全的运算符重载。它的命名源自美国逻辑学家 Haskell Brooks Curry,他在数学逻辑方面的工作使得函数式编程语言有了广泛的基础。在 Haskell 中,“函数是一等公民”。作为函数式编程语言,主要控制结构是函数。现在,Pandoc 和 PostgREST 等流行的开源项目使用 Haskell 编写的,后面我们还会讲到。
1991 年,Guido van Rossum 讨厌带有大括号的编程语言,于是他参考 Monty Python 和 Flying Circus 语法,发明了 Python。Python 是一种脚本语言,它使用严格的缩进来代替其他编程语言中的大括号。Python 生态中有很多用于科学计算的库,在人工智能大爆发的时代,Python 成了一门主流的编程语言。Python 语言的设计哲学是“优雅”、“明确”、“简单”。Python 语言的核心开发团队自称为“BDFL”(Benevolent Dictator For Life,终身仁慈的独裁者)。由于其简单易学、功能强大、应用广泛,Python 现在也是初学者首选的编程语言(相当于互联网时代的 Basic)。Python 生态中有很多科学计算和人工智能的库,比如 NumPy、SciPy、Pandas、Matplotlib、TensorFlow、PyTorch 等,基于这一点,Python 也是人工智能应用中首选的编程语言。
1993 年,Roberto Ierusalimschy 和他的朋友创造了一门巴西本地的脚本语言 Lua。在巴西语中,Lua 是月亮的意思。Lua 是一门小巧的“胶水”语言,经常用于将其它语言(如 C 语言)写的程序“粘”在一起,多用于游戏、数据库、Web 服务器、嵌入式等领域。Lua 语言的设计目标是成为一个可扩展、轻量级的脚本语言。有趣的是,不像其它语言,它的数组(在 Lua 中称为 Table)下标第一个元素是从 1 开始的,而不是 0。Lua 本质上是一门解释型语言,但也可以将 Lua 代码编译成一种中间格式(字节码),跨平台运行。另外,还有一个 LuaJIT 项目(Just-In-Time 编译器),可以将 Lua 代码编译成机器码,大大提高运行速度。
1994 年,Rasmus Lerdorf 为他个人主页的 CGI 脚本用 Perl 语言制作了一个模板引擎,用来统计他自己网站的访问量。后来又用 C 语言重新编写,还添加了数据库访问功能,就成了 PHP,最开始是 Personal Home Page 的缩写,后来改成了一个递归的缩写,即“PHP: Hypertext Preprocessor”,意思是“PHP:超文本预处理器”。PHP 是一种脚本语言,主要用于 Web 开发,可以嵌入 HTML。1995 年 6 月,PHP 1.0 发布。PHP 的语法借鉴了 C 语言、Java 和 Perl,易于学习和使用。随着 Web2.0 的大爆发,PHP 成了最流行的语言,“PHP 是最好的语言”的说法了逐渐流行开来。PHP 与 Linux、Apache、MySQL 简直是黄金搭档,合成 LAMP。2004 年 7 月发布的 PHP5 支持面向对象编程。PHP 语言的成功还有一个不可忽视的原因:PHP6 难产,直到 2015 年 12 月才有了 PHP7,这在一定程度上保证了 PHP 语言的稳定,用 PHP 写的程序在 10 多年内都不用考虑兼容问题。从这一点来看,倒有点跟 Windows XP 异曲同工。
1995 年,松本行弘发明了 Ruby 语言。这是一门动态脚本语言,它的设计哲学是“以人为本”,它的语法优美,非常适合初学者学习。然而 Ruby 语言一直不温不火,直到 2005 年,DHH(David Heinemeier Hansson)用 Ruby 开发出了 Ruby on Rails 框架,Ruby 语言才开始流行起来。Ruby on Rails 是一个 Web 开发框架,它的设计哲学是“约定胜于配置”(Convention over Configuration),通过约定来减少配置,使用 MVC (Model、View、Controller)框架很好地实现了各种约定,大大提高了开发效率。号称 5 分钟就可以完成一个 Todo List 或简单博客类的程序。Ruby on Rails 出现的时代也是互联网创业大爆发的时期,迅速成了创业公司的首选框架(可以很快地开发出原型拿到融资),比如 Twitter、GitHub、Shopify、Airbnb 等都是用 Ruby on Rails 开发的。当然,Ruby 语言也不全是优点,Ruby 语言的动态特性决定了它在运行时占用资源比较多,运行起来比较慢。
1995 年,Brendan Eich 利用周末时间设计了一种语言,用于为世界各地的网页浏览器提供支持,并最终推出了 Skynet。他最初去了 Netscape,并将这门语言命名为 LiveScript,后来在代码审查期间 Java 逐渐开始风靡,因此他们决定将其改名为 JavaScript,但实际是跟 Java 语言没有任何关系。后来 Java 使其陷入了商标麻烦,于是 JavaScript 被更名为 ECMAScript。但是人们还是习惯称之为 JavaScript。JavaScript 缩写为 JS,是浏览器中主流的脚本语言。与之相对的,IE 浏览器中另一个脚本语言 VBScript 仿佛从来没有流行过。JavaScript 语言的设计哲学是“一切都是对象”,它的语法借鉴了 C 语言和 Java 语言,但是它是一门解释型语言,不需要编译,直接在浏览器中运行。虽然它也可以设计在服务器端运行,但一直没有什么人用,直到后来出现了 Node.js。JavaScript 是一种单线程的语言,只能通过异步回调来实现并发。一方面,不用处理多线程,让程序写起来很简单;另一方面,程序往往会陷入回调地狱(Callback Hell),导致代码可读性变差。后来,为解决这个问题,出现了 Promise 和 async/await
语法糖。
1996 年,James Gosling 发明了 Java,这是第一个真正意义上面向对象得编程语言,其中设计模式在实用主义中占统治地位。Java 语言被设计成为一种跨平台的语言,它的口号是“一次编写到处运行”。它的语法借鉴了 C 语言和 C++ 语言,编译成字节码(Byte Code),然后在 Java 虚拟机(JVM)中运行。实至今日,Java 仍然是最流行的语言之一。事实上,Java 语言是一门真正工业级的语言,写起来方便、生态成熟,大量的工业级程序都是使用 Java 写的。后来,Android 平台上也选择了 Java 做为主流的开发语言。
微软于 1991 年发布了 Visual Basic 1.0,它是一个 Basic 编译器和 IDE,后来经过几个版本迭代随着 Windows 的发展大获成功。1993 年,微软发布了 Visual C++,后来又开发 Visual J++,这是微软版本的 Java 编译器和开发环境,然而,由于 Java 的版权问题没能继续。2001 年,安德斯·海尔斯伯格(Anders Hejlsberg)认为使用 C 语言的语法比起 Java 来说更酷,于是他参考 Java 的特征发明了 C#(读作 C-Sharp)。C# 现在是 Windows 环境主流的编程语言,也能跨平台使用。安德斯是个神人,他于 1960 年 12 月出生于丹麦哥本哈根,是 Turbo Pascal 编译器的主要作者。后 来 Borland 买下该编译器改为 Turbo Pascal,之后安德斯继续开发 Turbo Pascal,最终将其改为 Delphi。后被微软高薪挖走,参与了 Visual J++ 设计和开发,成为 C#和 TypeScript 之父,他也是.NET(dotnet)的创立者。
1999 年,沃尔特·布莱特创立了 D 语言,实作了第一个 D 语言编译器。D 语言创建的初衷是做一个更好的 C++。它是一门编译型语言,语法相当优雅,既拥有 Java 那样强大的表现力,又具有 C++ 相当的性能。D 语言支持闭包、匿名函数、编译时函数执行、支持垃圾回收等。D 语言本来是一门相当有吸引力的语言,然而,由于缺少大厂的支持以及缺少生态,而且,随着时间的发展 C++ 也变得越来越好,因此,D 语言一直没有流行起来。
Groovy 是一门基于 JVM 的脚本语言。它在兼容 Java 语法的同时,借鉴了 Ruby、Python 等语言的特性,有自己一套简洁而灵活的语法。同时,运行在 JVM 上也意味着它也可以使用 Java 语言编写的库。Groovy 的作者是 James Strachan,他于 2003 年在他的博客上分享了他的开发成果。2007 年 1 月,Groovy 发布 1.0 版。Groovy 本身是一个动态脚本语言,但也可以静态编译。
2006 年,Mozilla 员工 Graydon Hoare(他也是一个语言工程师) 开始做一个私人项目,也就是 Rust 语言。2009 年,Mozilla 开始赞助这个项目并于 2010 年首次对外发布。Rust 设计的目标人群是“被 C++ 所困扰的开发者”。C/C++ 一直是系统编程的首选,但由于内存安全、数据竞争等引起的问题也一直存在,Rust 的设计是从语言层面解决这些问题。Rust 没有运行时和垃圾回收器,所以性能非常高,而语言层面的内存安全也使得它写出来的程序非常可靠。当前,在 Windows 内核和 Linux 内核中都有实验性的使用 Rust 语言开发的部分,标志着 Rust 语言的成熟和被大家的认可。从 2016 年开始,Rust 每年都是开发者最爱的编程语言,但由于其学习曲线非常陡(太难学会),因此目前使用 Rust 的开发者占比并不高。
2006 年,麻省理工媒体实验室终身幼稚园组发布了 Scratch。Scratch 是一套以积木块为基础的可视化程序设计语言开发平台,于 150 多个国家和地区发行,并提供 60 多种语言版本(包括简体中文)。Scratch 由 Mitchel Resnick 和 Andrés Monroy-Hernández 创立。Scratch 最初可安装在 Mac OS X、Windows、Linux 的平台上;2.0 改使用 ActionScript 编制,3.0 改使用 HTML5 编制,并可运行于浏览器。Scratch 让程序设计语言初学者不需先学习语言语法便能设计项目。开发者期望通过学习制作 Scratch,启发和激励用户在愉快的环境下经由操作(如设计交互故事、多人游戏)去学习程序设计、数学和计算知识,同时获得创造性的思考、逻辑编程和协同工作的体验。Scratch 适用于所有年龄段的用户。即便用户从未学过程序设计,通过拖曳预先设定好的积木式程序模件,堆栈出指令,设置或控制角色及背景的行动和变化,从而完成程序撰写。Scratch 的运行界面如下图所示。
2009 年,在谷歌工作的 C 语言的创始人肯·汤普森和罗伯·派克(他们也都是 UNIX 的创始人)创建了一种类似 C 的编程语言,其更具安全性并且适合市场需求,它的吉祥物是一只地鼠。这门语句就是开源的 Go。Go 被称为互联网时代的 C,在云计算和云原生时代大放异彩,著名的 Docker 容器化管理程序就是用 Go 开发的。Go 语言“以程序员的生产力为中心”的语言,它语法简单,易于学习,同时它的并发编程能力也非常强大,可以轻松地编写出高并发的程序。Go 语言的作者认为,现在的计算机都是多核的,但是大多数编程语言都是单线程的,因此,Go 语言的设计目标是“让多核计算机发挥出它的全部威力”。此外,Go 语言还有一个倍受程序员喜爱的优点就是——编译速度非常快。
2011 年 10 月 10 日至 12 日在丹麦奥尔胡斯举行的 GOTO 大会上,谷歌正式发布了 Dart 语言。Dart 语言可用于 Web、服务器、移动应用和物联网等领域的开发。它是宽松开源许可证(修改的 BSD 证书)下的开源软件。Dart 是面向对象的、类定义的、单继承的语言。它的语法类似 C 语言,可以转译为 JavaScript,支持接口(interfaces)、混入(mixins)、抽象类(abstract classes)、具体化泛型(reified generics)、可选类型(optional typing)和强类型(sound type system)。2015 年 5 月 Dart 开发者峰会上,谷歌又推出了基于 Dart 语言的移动应用程序开发框架 Sky,后更名为 Flutter。
2011 年 7 月,JetBrains 推出 Kotlin 项目,这是一个面向 JVM 的新语言。Kotlin 可以编译成 Java 字节码,在 JVM 虚拟机上运行;也可以编译成 JavaScript,方便在没有 JVM 的设备上运行。除此之外 Kotlin 还可以编译成二进制代码直接运行在机器上(例如嵌入式设备或 iOS 上)。目前,Kotlin 已正式成为 Android 官方支持开发语言。在 Google I/O 2017 中,Google 宣布在 Android 上为 Kotlin 提供一等支持。。
2012 年,Anders Hjelsberg 想要在 Web 浏览器中合作 C#,于是他设计了 TypeScript。TypeScript 是 JavaScript 的超集,可以编译成纯 JavaScript 在浏览器里运行。与 JavaScript 相比,TypeScript 主要是规范了语法和增加了变量类型静态检查,这样,大多数错误在编译期就可以检查出来,而不像 JavaScript 那样到运行时(上线后)才会出现。
2013 年,Jeremy Ashkenas 想要拥有 Ruby 开发者那样愉快的开发体验,因此他创建了 CoffeeScript,它编译后是 JavaScript,但是看起来更像 Ruby。CoffeeScript 尝试用简洁的方式展示 JavaScript 优秀的部分。它的指导原则是:“她仅仅是 JavaScript” 代码一一对应地编译到 JavaScript,不会在编译过程中进行任何解释。已有的 JavaScript 类库可以无缝地和 CoffeeScript 搭配使用,反之亦然。编译后的 JavScript 代码是可读的,且经过美化,能在所有 JavaScript 环境中运行,并且应该和对应手写的 JavaScript 一样快或者更快.
2014 年,苹果推出了 Swift 编程语言,旨在让大家都能开发出众的 App。据说 Swift 从开始研发到最终发布仅用了不足 4 年时间。Swift 是一种支持多编程范式和编译式的开源编程语言,快速而高效,能够提供实时反馈,而且可以被无缝集成到现有的 Objective-C 代码中,因此,开发者能够编写安全而可靠的代码,并在节省时间的同时,创造出非常丰富的 App 体验。Swift 结合了 C 和 Objective-C 的优点并且不受 C 兼容性的限制。Swift 在 Mac OS 和 iOS 平台可以和 Object-C 使用相同的运行环境。目前,Swift 已经成为苹果开发的主要语言。
Zig 是由 Andrew Kelley 于 2015 年创建的开源编程语言。他的目标是设计一种现代化的系统级编程语言,结合了 C 语言的控制能力和高级语言的便利性。Zig 的发展始终坚持简单、安全和高效的原则,通过不断改进和迭代,逐渐成为一门备受开发者认可的语言。Zig 的语法类似于 C 语言,但在类型安全和错误检测方面更加强大。它支持静态类型检查、模块化编程、自动内存管理和编译时错误检测等特性。Zig 鼓励显式编程,强调代码的可读性和可维护性。它还提供了对内存布局和控制流的细粒度控制,使开发者能够精确地管理资源和优化性能。Zig 与 C 有很好的互操作性,事实上,Zig 致力于做一个更好的 C 并最终代替 C。
V 语言是 Alexander Medvednikov 开发的一门新的编译型语言,在 2019 年开始开发。V 语言最初是一个个人项目,后来以开源许可证发布。V 语言语法简单、运行速度快,内存安全,是一种编译型语言。它采用类似 Go 语言的语法,非常容易学。V 语言有垃圾回收,运行时也非常小,与 C 语言互操作没有额外开销(相对的 Go 语言的开销就比较大),最主要的是,它编译出来的软件体积非常小。V 语言已实现自举,其编译速度非常快(V 编译 V 耗时不超过 1 秒),可以编译成 C 再用 C 编译器编译,运行速度与 C 相当。V 语言的一切看起来都很美好,只是还比较年轻,目前缺少生态和大厂支持。
Elixir 是由 José Valim 在 2011 年创建的一种编程语言,它的作者之前曾参与维护 Ruby on Rails。简单来说,Elixir 就是集成了 Ruby、Ruby on Rails、Erlang 的一切优点的语言。它是一种函数式语言,为构建可扩展和可维护的网络应用而生,运行在可用于分布式和容错系统的 Erlang 虚拟机(BEAM)之上,支持低延迟和高并发。Phoenix 是一个 Elixir 版的类似 Ruby on Rails 的 Web 框架,借用了 Ruby on Rails 的一些顶级特性,并将它们的性能提升到了一个全新的水平。
2020 年左右,七牛的许式伟推出了一门新的语言叫 Go+。许式伟是 Go 语言在国内的布道者,发明 Go+ 也算是顺其自然的事情。Go+ 是一种静态编译型语言,有类似 Go 语言的语法,却更简单,又完全兼容 Go,可与 C 语言无缝对接。Go+ 提出了「三位一体」的概念,即面向工程,STEM 教育和数据科学。他觉得未来是全民编程的世界,也就是说人人都可以学编程。编程教育在未来,一定有越来越多的人会把它看作基础学科,和数学、语文、英语没有什么本质区别。此外,Go+ 还面向数据科学,因为未来有大是的数据需要进行计算。为了讲述数据科学和语言简单的重要性,他举过一个例子:Python 从诞生之初,并没有给自己数据科学语言的定位,它认为应该让语言尽量精简,容易被理解、被学习。所以它虽然没有将自己定位成数据科学语言,却成了数据科学的王者。这其实蛮讽刺的,因为有非常多专注于数据科学的语言都没有 Python 那么成功。
2023 年是生成式人工智能引领技术革命的一年。是 AI 大语言模型(LLM)大爆发的一年。以 OpenAI 的 GPT-4、Meta-LLaMA 等为代表的重量级产品和服务相继发布,AI 技术的蓬勃发展给编程语言带来了新的挑战和机遇。也诞生了两门值得关注的新编程语言:Mojo 和 MoonBit。
2023 年 9 月 7 日,Modular 公司宣布正式发布 Mojo。Mojo 是一个 AI 开发人员的新语言,它 结合了 Python 的可用性和 C/C++ 的性能,被设计为 Python 的超集。Mojo 语言有崇高的目标——与 Python 生态系统完全兼容,可预测低级性能和低级控制。据介绍,Mojo 最初的目标是比 Python 快 35000 倍,近日该团队表示,Mojo 将动态与静态语言的优点结合起来,一举将性能提升达 Python 的 68000 倍。Modular 公司由 LLVM 和 Swift 编程语言的联合创始人 Chris Lattner 创办。
MoonBit 是由前 OCaml 核心团队开发成员、ReScript 作者张宏波带领团队自研的工业级编程语言,专注为 AI 原生应用开发。MoonBit 作为一个 AI 时代下全新的开发平台,从一开始的顶层设计就考虑如何将传统 IDE 智能和大模型智能融合在一起。MoonBit 是为 AI 原生应用打造的编程语言,有专门为 AI 设计的编程语言与工具链,采用平坦化设计,适配 Transformer 架构,支持快速实时的语义补全,融合传统的 IDE 智能和大模型智能,是 AI 智能体的理想开发环境。
此外,还有一些“国产”编程语言,也值得一得。它们或者是国人自己设计实现的,或者(甚至)可以用“中文”编程。Go+算一个,其他典型的有凹语言(凹在此读 Wā),是一门语法类似 Go 的语言但面向 Web Assembly(一种在现代浏览器里运行的编码方式和程序框架)的;易语言和洛书都是中文编程语言;此外还有仓颉、木兰(Ulang)、Deeplang、Fanx、凸语言等,不一而足。
关于国产编程语言,我总体上是支持的。但是,国产编程语言不代表非要用中文编程。所谓编程语言中的“语言”,用到的只是一些符号,比如汇编语言中的MOV
指令、C 语言中的goto
以及for
等,本质上都是一些符号。当然,随着语言越来越高级,有些语言也越来越像自然语言,比如 C 语言中的 if (a > 4) printf("Hello")
在 Ruby 中也可以写成if a > 4 then puts "Hello" end
,也可以写成 puts "Hello" unless a <= 4
,而后者更接近自然语言。但无论如何它们还是些符号。中文编程语言号召大家用中文编程,但还是夹杂了很多英文符号,如洛书示例中,#循环(“10”)
包含了“#
”号,灯.闪烁.时间间隔(“500”)
中也包含了“.
”,在输入时还需要不断切换中英文输入法。中文编程的初心是对的,那就是为了让更多的人学会编程,但是,我认为在编程时记住几个英文的符号跟记汉字没有本质的区别,编程的核心还是逻辑(解决问题的方法,如条件判断、循环、算法等),而不是语言文字本身。C 语言(ANSI C)只有 32 个关键字,现在好多小学生都学英文,记住几个符号简直是轻而易举。我认为,对于英文的障碍,大多数人不是记不住编程使用的符号,而是在调试程序时,对编译或运行出错时输出的英文提示可能不理解。因此,比如对典型的 Lua 或 Python 等语言,稍加汉化,能在编程调试时输出中文的帮助和调试信息,就很好了。对于有 IDE 环境的语言,只要 IDE 是中文环境,有完善的中文帮助,就对编程很有帮助。
对于中文化编程的另一些支持者会讲到民族大义,要用中文影响全世界。这本质是没有错,但历史前进的方向和普遍规律就是让所有事情都更有效率。不管是编程的输入输出本身,还是调试过程、后续的维护、与其他人的沟通交流等,总是趋近于越来越简单、高效。这就像是从繁体字到简化字的演变一样,有些“国学”爱好者说简化字丧失了繁体字的历史意义和美感,但不可不承认,它对于我国在消除文盲方面起了多大作用4。同样,使用英文字母编程,也是最简单最有效的(至少比中文要简单,且更直观)。如果中文编程的初衷是影响全世界,那就用世界的眼光来看待编程,“师夷长技以制夷”,不是很好吗?退一万步讲,如果我们编程用中文,那学数学是不是也要用中文呢?数学符号中的英文 x、y、z 是不是也要写成甲、乙、丙?希腊字母 α、β、γ 用什么代替呢?总不能是写成阿尔法、贝塔、伽玛吧?
当然,我在此不是为了引起争论,也不是批评中文编程。事实上,有一种叫文言文(wenyan)的编程语言,我还挺喜欢的。在这门语言中,经典的 Hello World 程序是这样写的:“吾有一言。曰「「Hello world!」」。書之。” 看起来很酷。对于这种学习研究,应该鼓励。但我认为,没有必要鼓动所有人都去学文言编程或中文编程。
上面,我大体按时间顺序列举了几乎所有我知道的编程语言。有的语言我也没有真正使用过,但是,我觉得了解这些语言还是有好处的。特别是要思考它们为什么会出现,都能解决哪些问题。随着时代的发展,编程语言会越来越“高级”,但是低级的编程语言也永远会存在。我刚学习 C 语言的时候,C 还叫中级语言,现在看来越来越偏底层了。有好多项目都致力于做一个更好的 C,如 Zig、V、Rust,甚至 C++等,微软也有一个 Checked C 项目致力于做一个安全的 C 语言扩展。但是,不管世界怎么发展,C 的市场份额还一直很坚挺。很多高级语言也越来越现代化,如面向对向、引入函数式编程语法等,它们也相互借鉴学习,如用于后台开发的 C++、C#、Java、Go 之类的编译型语言;Ruby、Python、Javascript(Node.js)之类的脚本语言等,但为了向后兼容,它们也不可避免地越来越复杂。Kotlin、TypeScript、Groovy、CoffeeScript 等,它们都或者是把自己编译成其他语言,或者是在其他语言的虚拟机(如 JVM 或 BEAM)上运行,看起来就是些优化后的排列组合。下图是 TIOBE 编程语言指数统计图。可见 C 语言占有率一直比较稳定,近些年,Python 增长很快,C++ 和 C# 增长也比较稳定,尤其是 C# 竟然能了 2023 年度编程语言,应该跟 AIGC 的发展有很大关系,不知道是不是跟 Semantic Kernel5 有关。下表中也列出了 2024 年 1 月各种语言的排名及占比情况。
-
TIOBE 编程语言排名及占比(2024 年 1 月)
2024 年 1 月 | 2023 年 1 月 | 编程语言 | 占比 | 变化 |
---|---|---|---|---|
1 | 1 | Python | 13.97% | -2.39% |
2 | 2 | C | 11.44% | -4.81% |
3 | 3 | C++ | 9.96% | -2.95% |
4 | 4 | Java | 7.87% | -4.34% |
5 | 5 | C# | 7.16% | +1.43% |
6 | 7 | JavaScript | 2.77% | -0.11% |
7 | 10 | PHP | 1.79% | +0.40% |
8 | 6 | Visual Basic | 1.60% | -3.04% |
9 | 8 | SQL | 1.46% | -1.04% |
10 | 20 | Scratch | 1.44% | +0.86% |
11 | 12 | Go | 1.38% | +0.23% |
12 | 27 | Fortran | 1.09% | +0.64% |
13 | 17 | Delphi/Object Pascal | 1.09% | +0.36% |
14 | 15 | MATLAB | 0.97% | +0.06% |
15 | 9 | Assembly language | 0.92% | -0.68% |
16 | 11 | Swift | 0.89% | -0.31% |
17 | 25 | Kotlin | 0.85% | +0.37% |
18 | 16 | Ruby | 0.80% | +0.01% |
19 | 18 | Rust | 0.79% | +0.18% |
20 | 31 | COBOL | 0.78% | +0.45% |
随着技术的发展,“发明”一种新的编程语言也越来越容易。而且,随着世界变得越来越复杂,也将要有更多的问题需要解决,因此也可能有更多新的编程语言出现。本质上,编程语言就都是些“符号”,编译型语言如 C 会由编译器将这些符号编译成机器码,在 CPU 上执行;Java、Erlang 等语言则由编译器翻译成字节码(中间格式,便于跨平台),在 JVM 或 BEAM 虚拟机上执行(虚拟机再翻译成机器码);而脚本语言如 Python、Ruby 等则在运行时直接由语言解释器解释执行(动态翻译成机器码)。所以,“以不变应万变”,“数据结构 + 算法 = 程序”这个公式还是适用的,学好任何一门编程语言都可以举一反三,触类旁通。
再回到那个经典的问题:“我应该学习哪门语言呢?或者,我应该先学哪门语言呢?” 我认为,对于刚学编程的人来说,学任何语言都行。根据自己的情况和资源,找一门简单易上手的,如 Python、Javascript、Java,甚至 Scratch 都行。如果你是学生,那就按教学计划里的来。如果你已经参加工作半路出家想当程序员,那也看你要解决什么问题,手边有什么资源就学什么。当你能用一种语言编程序了,再去学习其他语言,也许你就知道自己要学什么了。总之,我认为学语言要“一专多能”,你要能精通一种语言,而这种语言大概率是你在工作中最常用的语言,如 Java、C#、Javascript 等。对于我自己而言,我觉得我学好了 C 语言对我自己帮助很大,因为 C 是一切语言的基础,我可以很容易地学习和理解其他语言。而作为一名程序员,不可能一辈子只用一种程序语言,毕竟,每种语言都有其特性,因此,多了解几种其他语言有助于在工作中更好地解决问题,也有助于对比学习,思考和学习各种语言的“解题思路”,与你的同事协作等。当然,你不需要所有语言都精通,如果你能找到更精通某种语言的人一起合作那是最好的事。而且,“人生有涯”,你也不可能所有语言都精通。就一个人以及一个项目而言,语言也不是越多越好。对个人而言,如果一种语言不常用,即使学会也很快会忘掉;对项目而言,引入一种新语言就意味着引入它所有的复杂度,包括它的优点和缺点,以及一大堆的工程问题:编译、发布、接口对接、测试、维护,以及各种不可预见的“坑”等等。
本文收录在《大道至简,给所有人看的编程书》第 3 章,讲述了编程语言的发展历史,以及各种编程语言的特点。
本文永久链接:https://www.dujinfang.com/2024/01/14/programming-languages.html 。
你都使用或喜欢哪些编程语言呢?欢迎留言告诉我。
-
参见 https://www.seas.upenn.edu/~zives/03f/cis550/codd.pdf 以及中文翻译 https://zhuanlan.zhihu.com/p/103655451 。 ↩
-
有的人主张复古,就是再改成繁体字,但我觉得这一定不会出现。不排除汉字在简化过程中有些“用力过猛”,如发财的“發”,和头发的“髮”在繁体字中是两个完全不同的字,但简体却是同一个。这种情况在未来可能会有微小的调整,但不会全面回归繁体字。 ↩
-
Semantic Kernel 是一个集成了各种大模型 API 的开发框架和 SDK,支持 C#、Python 和 Java,参见: https://github.com/microsoft/semantic-kernel 。 ↩