确实是一个微妙的问题......曾经是“解释”语言被解析并转换为执行速度更快的中间形式,但执行它们的“机器”是一个非常特定于语言的程序。“编译”语言被翻译成运行它的计算机支持的机器代码指令。早期的区别是非常基本的——静态与动态范围。在静态类型语言中,变量引用几乎可以在几条机器指令中解析为内存地址——您确切地知道变量在调用帧中引用的位置。在动态类型语言中,您必须搜索(在 A 列表或调用框架上)以获取参考。随着面向对象编程的出现,
实际上,可以追溯到 70 年代后期,编译语言和解释语言之间的区别并不大,而是它们是在编译环境中运行还是在解释环境中运行。例如,Pascal(我学习的第一个高级语言)在加州大学伯克利分校首先在 Bill Joy 的pxp解释器上运行,后来在他编写的编译器pcc上运行。相同的语言,在编译和解释环境中都可用。
有些语言比其他语言更具动态性,某物的含义——类型、方法、变量——取决于运行时环境。这意味着编译或不编译存在与执行程序相关的大量运行时机制。第四,Smalltalk、News、Lisp,都是这样的例子。最初,这些语言需要如此多的机制来执行(相对于 C 或 Fortran),它们是一种自然的解释。
甚至在 Java 之前,就有人尝试通过技巧、成为线程编译的技术、即时编译等来加速复杂、动态语言的执行。
不过,我认为是 Java,它是第一个真正混淆了编译器/解释器差距的广泛传播的语言,具有讽刺意味的是,它并不是为了让它运行得更快(尽管如此),而是让它可以在任何地方运行。通过定义自己的机器语言和“机器”java字节码和VM,Java试图成为一种编译成接近任何基本机器的语言,但实际上不是任何真正的机器。
现代语言结合了所有这些创新。有些具有传统“解释语言(ruby、lisp、smalltalk、python、perl(!))的动态、开放式、你不知道你得到什么直到运行时的性质,有些则试图具有严格的规范,允许对传统编译语言(java,scala)进行基于深度类型的静态错误检测。所有编译为实际的机器独立表示(JVM)以获得一次写入任何地方的语义。
那么,编译与解释?最好的,我会说。所有代码都在源代码中(带有文档),更改任何内容并且效果立竿见影,简单操作的运行速度几乎与硬件一样快,复杂的操作得到支持且速度足够快,硬件和内存模型在平台之间保持一致。
今天语言中更大的争论可能是它们是静态类型还是动态类型,也就是说不是它们运行的速度有多快,而是编译器会事先发现错误(代价是程序员必须指定相当复杂的类型信息)或错误会出现在测试和生产中。