系统学习计算机体系结构、汇编语言程序设计和编译原理,真正建立对计算机系统的理解,而不是臆测。推荐书《深入理解计算机系统》(如何读本书)或南京大学的 MOOC《计算机系统基础 (一):程序的表示、转换与链接》,它们包含以上三门课的基础知识。之后,便对知乎上大部分关于编程语言的概念性疑问豁然开朗。
用专业思维搞定这个疑问:发射到 CPU 最终执行的只有机器码,无论编程语言是编译型、解释型,还是混合型,无论是 AOT 还是 JIT,也无论是以面向过程、面向对象、泛型还是函数式设计思想编写程序。通俗地讲,CPU 不知道 C/C++、Java 和 Python 程序的存在,它只是无差别地执行机器码指令,各种编程语言只是为人类(程序员)发明的。所以,思考编程语言的运行机制时,思维不能停在半途,而应理清整个过程:某语言程序的执行文本(源代码),究竟是怎么传导为 CPU 的执行行为的(机器码指令)。
最基本的两种编程语言运行机制,代表了两种程序执行的传导方式:编译型 vs. 解释型。引自 CS143: Compilers, © Stanford University, Prof. Alex AikenCS143: 01-01 Introduction: Compilers vs. Interpreters
编译型和解释型语言,在语法分析时所用的技术是相通的。编译型的执行传导比解释型更直白,大学编译原理课重点一般放在编译型。要搞清解释型是怎么传导执行的,不浮于理论,最有效的学习途径是自制一个解释器。《手把手教你构建 C 语言编译器》(write-a-C-interpreter),以及 @vczh 十年前写的《手把手教你写脚本引擎》都是上手教程。
多种编程语言共存的意义
既然编程语言是为人类(程序员)发明的,必然遵循人类的思维习惯,这造就了千差万别的编程语言。影响语言设计的思维有两点:
(一) 人类思维是层次化的解决不同领域的问题,称为问题领域 (problem domain) 或应用领域 (application domain)。
一个具体问题,可分解为上中下多个层次,从底层的细节控制微调,到高层的模块组织协调。
导致产生多种程序设计范型,如面向过程的结构化设计、面向对象设计、泛型设计等。
(二) 人类思维是个性化的有人偏爱明确 (explicit),让程序员负责更多;有人偏爱隐含 (implicit),让 Runtime 负责更多。
现存于世的编程语言要比 TIOBE Index 上列出的多得多,那里列出的只是最流行的 Top 20。有大量个性化的、私人自制的语言系统默默无闻,但说不定此时正在你身边的设备上干活儿。这些语言甚至不是 turing-complete or general-purpose
有本《Masterminds of Programming》(中文版《编程之魂》翻译的不好)是对 C++、Python、Java 和 C# 等多个流行语言发明者的采访编录。文中有大量发明者关于语言特性的抉择和考虑。理解语言系统的 Runtime
Runtime 翻译为“运行时”,可以做状语,如 In C++, the instantiation of a template occurs in compile-time, while the instantiation of a class occurs in runtime.
Runtime 作为名词用时,一般是指某种语言系统的基础设施。但不同的执行传导方式下,Runtime 的作用不尽相同。
[1] C Runtime Library (CRT) 是 C 语言的 Runtime,作为古典编译型语言的典型。CRT 包含 ISO C 标准库的实现(不同厂商的扩展不同,微软的 MSVCRT 还包括 ISO C++ 标准库和它自己的一些扩展)。CRT 的主要作用,是根据各厂商实现的不同,初始化对于标准库有用的全局数据和结构,这些初始化在进入 main 函数之前就完成了,例如 stdin、stdout、stderr、errno 等。但作为 C/C++ 程序,是可以选择不链接、不使用 CRT 的,这仍是合法的 C/C++ 程序(尤其对于内核程序)。这时,需要自己实现 CRT 的某些功能。CRT 只是编程用户态程序的一种便利。
[2] Common Language Runtime (CLR) 是 .NET/Mono 语言 (C#, VB.NET, etc) 的 Runtime,作为 JIT 编译型语言的典型(也称为 Execution Engine 或 Virtual Machine,如微软的实现 mscoree.dll 称为 Microsoft .NET Runtime Execution Engine)。它的主要作用,是在运行时将 CIL 字节码转换为平台特定的机器码并传导执行。CLR 是不可或缺的,如下图:.NET CLI and CLR
Stanford Compilers 课程章节 01-03 The Economy of Programming Languages 中也讨论了多种编程语言共存的问题:CS143: 01-02 Languages Economy: Why are there so many programming languages?
[Q] 为什么有如此之多的编程语言?
[A] 因为应用领域千差万别。题目问题中的 C/C++、Java 和 Python,各自擅长的问题领域不尽相同。 以 C/C++ 为例,其擅长的系统编程,特点是 low-level control of resources (hardware / system)。就是让程序员负责更多的控制,而不是让类似 Java 的 Runtime (JVM) 接管太多事情。另一方面,C/C++ 程序对执行传导的立即响应要求上,Java 和 Python 也无法满足。CS143: 01-02 Languages Economy: Why are there new programming languages?CS143: 01-02 Languages Economy: Why are there new programming languages? (continued)
[Q] 为什么还会产生新的编程语言?
[A] 一个事实:对某种编程语言的学习和练习,是这个语言生态中最大的开销(时间和金钱)。当一种语言变得广泛流行(成熟),它的进化速度随之就会变慢。相反,新发明的语言的进化速度是很快的。新语言没有历史包袱,更容易占领新(突发)出现的生态位。但新语言也会参考成熟语言的某些风格。CS143: 01-02 Languages Economy: What is a good programming languages?
[Q] 什么是好的编程语言?
[A] 不存在一个普适的标准,在一个框架下,评估所有编程语言的优劣。有一种“存在即合理”的说法:有人用的语言就是好的语言。但 Aiken 教授并不同意,反例是 VB 用的人很多,VB 难道是最好的语言之一?
参考