Duby和Juby有什么区别,我为什么需要它们?

20

根据Charles NutterDuby是一种静态类型语言,具有Ruby的语法和Java的类型系统。

Duby支持所有Ruby的字面量,使用本地类型推断(只需声明参数类型),并且与Java一样快(因为它生成几乎相同的字节码)。但是随着invokedynamic的出现,Duby需要一个伙伴。

1. invokedynamic是什么,为什么Duby“需要一个伙伴”?

另一方面,Juby是这样的:

Juby旨在基本上像Duby一样,因为它使用Java的类型和Ruby的语法。但它利用了新的invokedynamic操作码来实现100%的动态性。Juby是一种动态Duby,或者可能是具有Ruby语法的动态Java。它不难理解。

实际上,这很难理解。

2. 有人能更详细地解释一下这个区别吗?

3. 我们为什么需要(需要!)另一种与Ruby相关的语言?或者,更准确地说,需要两种与Ruby相关的语言吗?

5个回答

50

我将按照相反的顺序回答问题,从最简单的问题开始:

2. 有人能详细解释一下这个区别吗?

Duby是静态类型的,Surinx(曾经被称为Juby的名称)是动态类型的。这就是全部内容。

实际上,这里有一个小细节作为其结果:Surinx语法是Ruby语法的严格子集,即每个句法有效的Surinx程序也是一个句法有效的Ruby程序。然而,Duby几乎是一个句法子集,除了其强制性方法参数类型注释:

def foo(bar => Integer, baz => String) => Array
  # ...
end

这在Ruby中是非法的。

3. 为什么我们需要(需要!)另一种与Ruby相关的语言?

首先:除了语法上的相似之外,这些语言与Ruby毫不相关。

那么,为什么Charles Oliver Nutter创建了Duby?他是JRuby Ruby实现的首席开发人员,这是JVM上Ruby编程语言的实现。像大多数Ruby实现一样,它是用底层平台的主导编程语言编写的:MRIYARVtinyrb都是100%用C实现的,MacRuby主要用C和少量Objective-C实现,Ruby.NETIronRuby 100%用C#实现,HotRubyECMAScript实现,Red Sun用ActionScript实现,Cardinal用PIR和NQP实现等等。(唯一包含大量Ruby代码的Ruby实现是Rubinius(约70%Ruby,30% C++)和MagLev(未知数量的RubySmalltalk)。)自然,XRubyJRuby都是100%用Java实现的。

现在,有趣的是,Charlie 来到了 Ruby,因为他不喜欢他的日常工作——Java开发。而现在,他整天都在写Java代码!当然,他不喜欢这个,所以他正在寻找另一种编程语言来实现JRuby的核心。一种选择肯定是只用Ruby来写它,但是随着元循环实现的出现,通常会出现收益递减的情况,其中实现退化为学术上的自我陶醉。重写库、提前编译器(实际上,已经在做了)和一些核心类在Ruby中肯定是有意义的,但是引擎核心的某些部分最好是用更接近JVM执行模型的语言编写。

Charlie 正在查看可用的选项:ScalaGroovyFanClojureNice,但它们都有一个明显的缺点:相当大的语言运行时。JRuby 运行时的大小已经是内存消耗和启动延迟的一个大问题(特别是与 MRIYARV 相比,如果您实际上将 JVM 本身包含在您的测量中,情况会更糟),而将其重写为一种添加了自己的运行时的语言就根本不可行。不幸的是,没有一种编程语言满足 Charlie 寻找的两个基本标准:没有运行时且能够编译成至少与等效 Java 一样高效的 JVM 字节码。

所以,他决定创建自己的编程语言。他选择使用与Ruby类似的语法的原因其实很简单:他不需要为此编写解析器,Duby只是使用JRuby已经存在的解析器,并做了一点小修改以支持方法参数类型注释。(实际上,他也喜欢Ruby的语法,这当然也是一个因素。)

正如你所知,语法实际上是编程语言中最不重要的部分。(它的无关性并不总是明显的 从争论的数量来看,但这只是因为语法是唯一可以争论而不必真正理解自己在说什么的东西。)比语法更重要的是类型系统和求值语义。这里有一个诀窍:Duby 没有这两个!它 只有 语法!它就像是寄生虫:它只是从底层平台“借用”类型系统和语义。这意味着在 JVM 上,Duby 的类型系统 Java 类型系统,Duby 的语义 Java 的语义。换句话说:Duby 根本不是一种编程语言,而是 Java 的“替代语法”。

这意味着Duby和Java之间没有映射、转换开销和速度差异。这也意味着JRuby内部可以用Duby编写,而不会失去任何功能。

所以,这就是Duby

为了解释Surinx,我将首先回答你的第一个问题:

1. invokedynamic是什么,为什么Duby "需要一个玩伴"?

invokedynamic是一种新的字节码,将被添加到JVM规范的第三版中,并将在JDK7中发布。然而,更普遍地说,invokedynamic通常用作代表一系列功能的替身,其中实际的invokedynamic bytecode只是其中之一,这些功能目前正在JSR-292“在Java平台上支持动态类型语言”的框架下开发。更普遍地说,名称invokedynamic被用作Sun和整个JCP转变Java平台成为各种语言的通用语言平台的总体策略的代名词。

JSR-292的具体目的(Charlie在他的博客文章中提到的)是使动态方法分派更快 - 至少在最佳情况下,它几乎像Java中的静态分派一样快。

Surinx是一种动态类型编程语言,基本上与Duby做了相同的事情:像Duby一样,它只有语法,像Duby一样,它使用Java类型系统。但是,与Duby不同的是,它使用Java的方法调用语义,而是使用invokedynamics方法调用语义。换句话说:它是动态类型的,并使用动态分派。

所以,这就是Surinx

现在,我可以回答你第三个问题的后半部分:
3. 为什么我们需要(需要!)另外两种与Ruby相关的语言?
我已经回答了Duby,这里是Surinx的答案:它就是Groovy应该成为的轻量级(实际上是零重量)动态表达式脚本语言,适用于JVM。此外,它目前是探索invokedynamic内部工作方式最简单的方法。(JRuby 1.4的当前开发快照也支持它,但那是一个更复杂的项目。)

我忘了说两件事情:Duby 实际上使用本地变量类型推断,因此,与 Java 不同,您只需要声明方法参数的类型,但是方法中的所有内容都将被推断类型。

其次,DubySurinx都不是与JVM绑定的。由于它们只是从底层平台窃取其语义和类型系统,因此它们几乎可以在任何地方进行移植,只要你有一个从Ruby语法到平台概念的大致映射。我能想到的是,将Duby移植到C、C++、Objective-C(iPhone,任何人?)、DCLI和ActionScript,将Surinx移植到DLRSmalltalkParrotECMAScriptPythonPerlPHP和Objectice-C。实际上,已经开始了C移植Duby的工作。


感谢您提供如此结构清晰、全面详尽的答案。 - jabley
1
正如你所知,语法实际上是编程语言中最不重要的部分。这个评论对duby在java语义基础上进行语法改变的优点的赞扬之辞,让人感到非常讽刺。 - jshen
1
@jshen:很高兴有人发现了其中的讽刺意味 :-) 然而,这实际上不仅仅是语法问题:我在帖子中提到了类型推断。还有闭包。而且,截至今天,Duby也支持动态分派(换句话说,Duby是新的Surinx)。Java中没有这三个功能。此外,虽然语法不会改变语言的表达能力,但它确实会改变“表达方便性”。我承认,在试图定义Duby时,我倾向于夸张:许多人认为它只是Ruby的另一种实现,我想尽可能清楚地表明Duby与Ruby相去甚远。 - Jörg W Mittag
Jorg,我在我的早间博客文章中添加了你的几个回答(这里只有片段和链接)。感谢你出色的回答。 - Mark Essel
@Mark Essel:顺便说一下,两周前动态类型支持已经合并到了Duby中,因此Surinx已经过时了。此外,一些谷歌员工对Duby进行了大量的开发,用于Google应用引擎和Android开发。(这个主题已经有几个视频演讲了。) - Jörg W Mittag
我对那些 Jorg(通过 Ola Bini 观看了一段很棒的视频)非常着迷,并且一直在享受人们对 Ruby/Ruby-Like 优化工作和 Java 兼容性所给予的关注。对于数值密集型处理,MRI 的速度还不够快,但在我看来,Ruby 的长期表现能力无与伦比。 - Mark Essel

6
Mirah(原名Duby)存在的原因是,静态类型可以通过Java / Hotspot实现显着的性能提升。Surinx(原名Juby)也是同样的东西,只是它还利用了即将在JDK7中推出的新的性能特性来进一步提高性能。
这个性能特性通常被称为“invokedynamic”,Nutter's blog上有一个很好的解释。

1
但是为什么不直接将性能特性添加到Duby中呢?为什么要创建一个全新的语言?如果每次想要添加一个特性就创建一个新的语言……你知道我要说什么。 - Michael Stockman
2
@Michael:我怀疑这是由于渴望尝试和缺乏invokedynamic的可用性驱动的。在JDK7之前,Duby可能很有用,而在JDK7+中,Juby可能很有用。 - jsight
2
Duby和Surinx并不是“同一件事”!实际上,在某种意义上,它们几乎是相反的:Duby是静态类型的,Surinx是动态类型的。整个回答基本上都是虚构的。而且还很糟糕。 - Jörg W Mittag
@ - Jörg - Nutter在这里的术语对我来说有点令人困惑。直接引用页面上的话:“Juby的目标基本上就像Duby一样,它使用Java的类型和Ruby的语法。”如果它们是完全相反的,为什么他说它“基本上像Duby”呢?我认为它们确实非常相似... Duby使用局部类型推断(除了方法调用)。Juby是动态类型的,包括通过invokedynamic进行的方法调用。 - jsight
@Telemachus,或者甚至是“Scooby Dooby Doo” :-) - Alex Blakemore

4

刚刚看到这篇文章,直接来自Charles本人的话,部分回答了问题(关于它们之间的区别):

这就引出了Surinx的未来。它甚至比Duby的未来更简单:它们两个将合并。由于我已经同时在Surinx和Duby上工作过,我发现它们本质上是相同的语言,只是具有不同的调度机制和类型声明要求。而且,由于Duby可以轻松地将未经类型标注或动态类型标注的表达式视为需要动态调用,所以没有理由让Surinx不成为Duby的一个功能。


2
截至今天,合并已经完成。 - Jörg W Mittag

3

就像语言一样,我们不是因为“需要”而创造它们。人们出于各种原因创造它们,除非我们需要它们,否则它们将保持默默无闻。

有很多晦涩难懂的语言存在;它们很有趣,但可能不适合在真正的项目中使用。


例如:Brainfuck: >[-]>[-]<<[->+>+<<] (它将内存位置1和2设置为内存位置0的内容) - Thorbjørn Ravn Andersen

2
我怀疑,在某些时候,我可能能够用普通的动态Ruby原型化一段代码,并且当它能够运行但需要显著提高速度时,将其移植到一种相关的语言中,该语言将编译为优化的JIT Java字节码,而且移植过程相对较少痛苦。或者可能是IronRuby#.NET、Sapphire或其他什么东西。

图形处理、重型数学、人工智能等等。我觉得我会在做这些事情时很有乐趣……


我认为这就是JRUBY提供的优势或多或少吧。我的意思是,它没有被编译过,但是JRUBY解释器比MRI快得多(不知道1.9怎么样)。也许你所说的是这是更进一步的一步 - 比最快的解释器更快。 - Michael Stockman
2
这是我的理解(请参见http://en.wikipedia.org/wiki/JRuby#Performance)- Charles现在谈论的是一系列基于Ruby的语言,其性能大致与纯JIT化的Java相同。 换句话说,速度很快。 - Mike Woodhouse

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