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

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

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

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

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

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

是的,Ruby仍然是一种解释性语言,或者更确切地说,Matz的Ruby解释器(MRI),这是人们在谈论Ruby时通常谈论的,仍然是一个解释器。 编译步骤就是将代码简化为比执行更快的代码,而不是一次又一次地解释和重新解释相同的代码。

如果将字节码计算为编译,现在几乎每种语言都被“编译”了。 甚至Emacs Lisp也被编译了。 Ruby是一个特殊情况,因为直到最近,它还没有被编译成字节码。

我认为你质疑将语言描述为“编译”与“解释”的效用是正确的。 但是,一个有用的区别是语言是否直接从用户代码创建机器代码(例如x86汇编程序)。 C,C ++,许多Lisps和启用了JIT的Java都可以,但是Ruby,Python和Perl都没有。

不熟悉的人会将任何具有“编译”的单独手动编译步骤的语言称为“未解释”的语言。

确实是一个微妙的问题……过去,“解释”语言被解析并转换为执行速度更快的中间forms,但执行它们的“机器”是一个非常适合语言的程序。 “编译”语言被转换为运行它的计算机支持的机器代码指令。 早期的区别非常基本 – 静态与动态范围。 在静态类型语言中,变量引用几乎可以解析为几个机器指令中的内存地址 – 您确切地知道变量引用的调用帧中的哪个位置。 在动态类型语言中,您必须搜索(向上A列或向上调用帧)以供参考。 随着面向对象编程的出现,参考的非直接性质扩展到更多的概念 – 类(类型),方法(函数),甚至语法解释(嵌入式DSL,如正则表达式)。

事实上,回到70年代后期的区别并不是编译语言和解释语言之间的区别,而是它们是在编译环境还是解释环境中运行。 例如,Pascal(我研究过的第一门高级语言)首先在加州大学伯克利分校竞选Bill Joy的pxp解释器,后来又编写了编写pcc的编译器。 相同的语言,在编译和解释环境中都可用。

有些语言比其他语言更具动态性,某种东西的含义 – 类型,方法,变量 – 取决于运行时环境。 这意味着编译或不编译与执行程序相关的实质性运行时机制。 Forth,Smalltalk,NeWs,Lisp,都是这方面的例子。 最初,这些语言需要如此多的机制来执行(相对于C或Fortran),它们是解释的自然。

甚至在Java之前,就有人试图通过技巧加速执行复杂的动态语言,这些技术变成了线程编译,即时编译等等。

我认为这是Java,它是第一种广泛使用的语言,它真正混淆了编译器/解释器的差距,具有讽刺意味的是,它不会运行得更快(尽管如此),但它会在任何地方运行。 通过定义自己的机器语言和“机器”java字节码和VM,Java试图成为一种语言,编译成接近任何基本机器的东西,但实际上并不是任何真正的机器。

现代语言与所有这些创新相结合。 有些人有动态的,开放式的,你不知道你在运行时的性质,传统的“解释语言(ruby,lisp,smalltalk,python,perl(!)),有些尝试具有严格的规范允许传统编译语言(java,scala)的基于深度类型的静态错误检测。所有编译到实际的机器无关表示(JVM),以便在任何地方语义上运行。

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

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

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

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

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

这可能有点偏离主题,但……

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

至于我从上海的RubyConf 2011获得的信息,Matz正在开发一种’MRuby’(代表Matz的Ruby),以便在嵌入式设备上运行。 Matz表示,MRuby将提供将ruby代码编译成机器代码的能力,以提高速度并减少嵌入式设备上(有限)资源的使用。 因此,有各种类型的Ruby实现,并且绝对不是所有这些实现都只是在运行时解释。