16

在为这个关于 Blue Ruby的问题选择的答案中,Chuck 说:

当前所有的 Ruby 实现都被编译为字节码。与 SAP 的说法相反,从 Ruby 1.9 开始,MRI 本身包括一个字节码编译器,尽管在合并 YARV 虚拟机的过程中,将编译后的字节码保存到磁盘的能力消失了。JRuby 被编译成 Java .class 文件。我没有太多关于 MagLev 的细节,但可以肯定地说它也会走这条路。

我对这个关于 Ruby 的编译/解释问题感到困惑。

我了解到 Ruby 是一种解释型语言,这就是为什么当我将更改保存到我的 Ruby 文件时,我不需要重新构建项目。

但是,如果现在所有的 Ruby 实现都被编译了,那么说 Ruby 是一种解释型语言还公平吗?还是我误解了什么?

4

7 回答 7

21

如果您将字节码视为已编译,那么如今几乎每种语言都已“编译”。甚至 Emacs Lisp 也是编译好的。Ruby 是一个特例,因为直到最近,它还没有被编译成字节码。

我认为您对将语言表征为“编译”与“解释”的效用提出质疑是正确的。不过,一个有用的区别是该语言是否直接从用户代码创建机器代码(例如 x86 汇编程序)。C、C++、许多 Lisps 和启用 JIT 的 Java 可以,但 Ruby、Python 和 Perl 不可以。

不太了解的人会将任何具有单独手动编译步骤的语言称为“已编译”,而没有“解释”的语言。

于 2009-04-04T17:54:21.453 回答
19

是的,Ruby 仍然是一种解释性语言,或者更准确地说,人们在谈论 Ruby 时通常会谈论的 Matz 的 Ruby Interpreter (MRI) 仍然是一种解释器。编译步骤只是为了将代码减少到比一次又一次地解释和重新解释相同的代码执行得更快的东西。

于 2009-04-04T17:51:34.593 回答
8

确实是一个微妙的问题......曾经是“解释”语言被解析并转换为执行速度更快的中间形式,但执行它们的“机器”是一个非常特定于语言的程序。“编译”语言被翻译成运行它的计算机支持的机器代码指令。早期的区别是非常基本的——静态与动态范围。在静态类型语言中,变量引用几乎可以在几条机器指令中解析为内存地址——您确切地知道变量在调用帧中引用的位置。在动态类型语言中,您必须搜索(在 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)以获得一次写入任何地方的语义。

那么,编译与解释?最好的,我会说。所有代码都在源代码中(带有文档),更改任何内容并且效果立竿见影,简单操作的运行速度几乎与硬件一样快,复杂的操作得到支持且速度足够快,硬件和内存模型在平台之间保持一致。

今天语言中更大的争论可能是它们是静态类型还是动态类型,也就是说不是它们运行的​​速度有多快,而是编译器会事先发现错误(代价是程序员必须指定相当复杂的类型信息)或错误会出现在测试和生产中。

于 2011-06-02T05:58:45.997 回答
3

您可以使用交互式 Ruby Shell irb交互式地运行 Ruby程序。虽然它可能会生成中间字节码,但它肯定不是传统意义上的“编译器”。

于 2009-04-04T17:51:01.570 回答
3

编译语言通常被编译成机器码,而不仅仅是字节码。不过,一些字节码生成器实际上可以进一步将字节码编译成机器码。

字节码本身只是用户编写的文字代码和虚拟机之间的中间步骤,但它仍然需要由虚拟机解释(就像它在 JVM 中使用 Java 和带有操作码缓存的 PHP 一样)。

于 2009-04-04T17:52:57.977 回答
0

这可能有点跑题了,但是...

Iron Ruby是基于 .net 的 ruby​​ 实现,因此通常编译为字节码,然后在运行时 JIT 编译为机器语言(即不解释)。此外(至少对于其他 .net 语言,所以我假设使用 ruby​​)ngen可用于提前生成已编译的本机二进制文件,因此这实际上是 ruby​​ 代码的机器代码编译版本。

于 2009-04-04T19:32:39.080 回答
0

至于我从上海 RubyConf 2011 得到的信息,Matz 正在开发一个“MRuby”(代表 Matz's Ruby),以在嵌入式设备上运行。Matz 表示,MRuby 将提供将 ruby​​ 代码编译为机器代码的能力,以提高速度并减少嵌入式设备上(有限)资源的使用。所以,有各种各样的 Ruby 实现,绝对不是所有的都只是在运行时解释。

于 2011-11-27T02:09:23.227 回答