如果所有Ruby的实现都被编译成字节码,那么它是否真的是一种解释性语言?

17
这个关于Blue Ruby的问题中,选择的答案中,Chuck说:
所有当前的Ruby实现都被编译成字节码。与SAP的声明相反,在Ruby 1.9中,MRI本身包括一个字节码编译器,尽管将已编译的字节码保存到磁盘的能力在合并YARV虚拟机的过程中消失了。JRuby被编译成Java .class文件。我对MagLev没有太多细节,但可以肯定的是它也会走这条路线。
我对Ruby的编译/解释问题感到困惑。
我了解到Ruby是一种解释性语言,这就是为什么当我保存对我的Ruby文件的更改时,我不需要重新构建项目。
但如果现在所有的Ruby实现都被编译了,那么是否仍然可以说Ruby是一种解释性语言?或者我误解了什么?

为了澄清,我所提到的SAP文章也谈到了编译成字节码。因此,如果我们将VM字节码视为“已编译”(我可以看到支持和反对的论点),那么MRI肯定是已编译的。 - Chuck
7个回答

22
现在几乎所有语言都被“编译”,如果你将字节码视为编译,即使Emacs Lisp也被编译了。直到最近,Ruby是个特例,因为它不会被编译成字节码。
我认为你对将语言归为“编译”和“解释”的效用提出了质疑是正确的。但有一个有用的区别是该语言是否可以直接从用户代码生成机器码(如x86汇编)。C、C ++、许多Lisp和启用JIT的Java可以,但Ruby、Python和Perl不行。
那些不了解情况的人会称带有单独手动编译步骤的任何语言为“编译语言”,而没有这种步骤的则称为“解释语言”。

1
启用JIT的Java...难道不应该禁用JIT吗?因为JIT是将字节码编译成机器代码。因此,如果编译器生成要进行JIT编译的内容,它就不会生成机器代码。 - stonedauwg

19

是的,Ruby仍然是一种解释性语言,更确切地说,当人们谈论Ruby时,通常会提到Matz's Ruby Interpreter (MRI),它仍然是一种解释器。编译步骤只是为了将代码转换为可执行速度更快的形式,而不是反复解释和重新解释相同的代码。


8
一个微妙的问题... 过去,“解释”语言被解析并转换为一种中间形式,这种形式执行起来更快,但执行它们的“机器”是一个相当特定于语言的程序。“编译”语言则被翻译成计算机支持的机器代码指令。早期的区别非常基本——静态与动态范围。在静态类型语言中,变量引用可以很容易地通过几个机器指令解析为内存地址,你知道变量所指的调用帧的确切位置。在动态类型语言中,你必须搜索(向上搜索A列表或调用框架)来查找引用。随着面向对象编程的出现,引用的非立即性质扩展到了更多的概念——类(类型)、方法(函数),甚至是语法解释(嵌入式DSL,如正则表达式)。
实际上,回溯到大约70年代末,区别不是在于编译和解释语言之间,而是它们是否在编译或解释环境中运行。例如,Pascal(我学习的第一种高级语言)首先在UC Berkeley上运行在Bill Joy的pxp解释器上,后来在他编写的编译器pcc上运行。同一种语言,在编译和解释环境中都可用。
有些语言比其他语言更动态,某些东西的含义——类型、方法、变量——取决于运行时环境。这意味着无论编译与否,执行程序都需要大量的运行时机制。Forth、Smalltalk、NeWs、Lisp都是这种情况的例子。最初,这些语言执行所需的机制(相对于C或Fortran)如此之多,以至于它们自然而然地被解释。
甚至在Java之前,已经有了加速执行复杂、动态语言的尝试,使用了各种技巧和技术,这些技术成为了线程编译、即时编译等。
我认为是Java首先广泛使用的语言,真正模糊了编译器/解释器间隔,具有讽刺意味的是,不是为了使其运行更快(尽管也是),而是为了使其运行到任何地方。通过定义他们自己的机器语言和“机器”Java字节码和VM,Java试图将语言编译成接近任何基本机器但实际上不是任何真实机器的东西。
现代语言将所有这些创新融合在一起。一些语言具有传统“解释语言”的动态、开放式、直到运行时才知道你得到了什么的特性(ruby、lisp、smalltalk、python、perl(!)),一些则尝试具有规范的严格性,允许传统编译语言的深层次基于类型的静态错误检测(Java、scala)。所有这些语言都编译成实际的机器无关表示(JVM),以获得一次编写,到处运行的语义。
所以,编译还是解释?我想说最好两者兼备。所有的代码都在源代码中(带有文档),更改任何内容都会立即生效,简单的操作几乎与硬件能够执行它们的速度一样快,复杂的操作得到支持并且足够快,硬件和内存模型在各个平台

当今语言中的一个大争议可能是它们是静态类型还是动态类型,这意味着不是它们运行得有多快,而是编译器是否会事先发现错误(以程序员必须指定相当复杂的类型信息为代价),还是在测试和生产中出现错误。


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

3

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

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


0

这可能有点离题,但是...

Iron Ruby 是基于 .net 的 Ruby 实现,因此通常会被编译为字节码,然后在运行时 JIT 编译为机器语言(即非解释性)。此外(至少对于其他 .net 语言,因此我认为对于 Ruby 也是如此),ngen 可以用来预先生成编译的本地二进制文件,因此这实际上是 Ruby 代码的机器码编译版本。


0
关于我从2011年在上海举办的RubyConf获得的信息,Matz正在开发一个名为'MRuby'(代表Matz的Ruby)的东西,旨在针对嵌入式设备运行。Matz说MRuby将提供将Ruby代码编译成机器码以提高速度并减少嵌入式设备上(有限的)资源使用的能力。因此,有各种各样的Ruby实现,肯定不是所有实现都只在运行时解释。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接