1.1 Ruby语言与JRuby语言

在本节中,首先介绍Ruby语言的概念及其历史和理念,然后介绍Ruby语言与JRuby语言的相互关系。

一般来讲,对“Ruby语言”概念的理解可以有“广义”和“狭义”两种,所谓“广义”理解就是指它是一门计算机语言的技术规范;“狭义”理解则是指这门语言的一个具体实现。

1.1.1 什么是Ruby语言

Ruby语言是一种面向对象的、动态的解释性语言,它是由日本人松本行弘(まつもとゆきひろ,英译:Yukihiro Matsumoto,外号Matz)开发完成的。长期以来,松本行弘一直想发明一种语言,该语言不仅能够使软件开发人员进行高效的开发工作而且又能享受到编程的快乐。于是从1993年2月24日开始,他正式启动了Ruby语言的研发工作,1995年12月正式公开发布了Ruby的第一个版本:Ruby 0.95。该语言的发行遵守GPL协议和Ruby License。

Ruby语言是一门特高级语言(Very High-Level Language,VHLL)。它可以通过编写较少的指令来控制复杂的数据结构并对其进行灵活的操作,符合程序设计“最少投入原则”(Principle of Least Effort)。

Ruby语言是一门脚本语言。它可以使传统的、烦琐的脚本操作变得更容易编程,比如运行外部程序、检查系统资源、使用管道(pipe)、截获子进程状态和截获程序输出信息等。

Ruby语言是一门动态语言。这意味着方法和变量可以在程序的运行过程中进行添加和重定义,不仅减少了像C语言那样的条件编译(#ifdef),而且容易实现反射技术(reflection)。

Ruby语言是一门解释型语言。其最为显著的特点就是快速的开发周期(rapid development cycle)。比如Ruby on Rails就是一个很好的实例,它前所未有地加速和简化了网站的构建。可以预料,随着计算机硬件设备性能的持续提高,Ruby语言的性能将会得到更大的提高。

关于Ruby语言的名字来历,有这样一种说法:因为Perl的发音与6月的诞生石pearl(珍珠)相同,因此,Matz就以7月的诞生石ruby(红宝石)为该语言命名。

目前,Ruby语言的稳定版本是1.8.6(2007年3月12日发布)。这个版本也是当前应用得最为广泛的一个版本,它是用C语言实现的。

1.1.2 开发Ruby语言的理念

早期的许多程序设计语言,由于受到机器性能的约束,所以其设计必须是以机器为主,关注机器的执行性能。随着计算机技术尤其是硬件技术的持续快速发展,机器性能得到了很大的提高,人们的设计思维也从“关注机器性能”逐步转向如何适应人的角度来考虑问题,换句话说,要求体现出人本主义的思想。

由于Matz研发的Ruby语言十分强调系统设计的人性化,“一直想发明一种语言,使你既能进行高效开发又能享受编程的快乐”,所以,该语言引人瞩目,一经推出,便很快地吸引了一大批的拥护者。在Matz看来,好的编程语言一定要能减少编程人员的工作量,节省时间,消除浪费,同时又能使编写程序的工作成为一件令人愉快的事情。

事实上,也正是因为Ruby语言遵循了上述的设计理念,所以才非常直观,并且按照人们的习惯思维方式运行。

1.1.3 Ruby语言特性

Matz是这样形容Ruby的:Ruby >(Smalltalk + Perl)/ 2。其含义就是:Ruby语言在语法上像Smalltalk,是完全面向对象的脚本执行语言,在功能上又具有类似于Perl的强大的文字处理功能。Ruby语言的这种编程特点,使得人们可以方便、快捷地进行面向对象的编程,不仅简单明了,而且扩展性强,移植性好。

Ruby语言的主要特色:

1. 语法简单

(1)传递一切可以传递的代码。代码块(Blocks,如“...”和“do…end”)技术可以被引用。第8章将通过实例详细说明有关内容;

(2)动态一切可以动态的代码。开发人员不必在编译前就定义数组大小,也不必预先为数组分配内存空间,更不必时刻警惕其长度。如使用整数时不用考虑它内在的形式,因为Ruby语言会根据数值的大小自动选定使用Fixnum类还是Bignum类。后面将会给出实例;

(3)迭代一切可以迭代的代码。迭代器(iterator)功能强大,像“把代码块传递到对象中”这种操作可以轻易完成,如对于数组、列表(list)、树(tree)等数据结构中的每一个元素都能够调用指定的代码块;

(4)忽略一切可以忽略的代码和符号。比如在函数调用中可以忽略括号;参数之间可以忽略逗号;函数返回的关键字“return”也可以忽略;如果仅仅只有一行代码,则连语句尾的分号也可以忽略;

(5)简化一切可以简化的代码。可以用“for a in x”来迭代遍历数组对象x;可以用“a+= b”来代替“a = a + b”;

(6)表达一切可使用英语的表达方式(expression-oriented)。例如在Rails框架中,可以采用“20.minutes.ago”代码来表达“二十分钟之前”的含义。

2. 理念新意

(1)一切都是对象。Ruby语言,从一开始就以面向对象为目标来设计,是一门完完全全的、纯粹的面向对象语言。Ruby语言中的所有元素都是对象。任何数据都是对象,包括在其他语言中的基本类型(比如:整数、布尔逻辑值),每个函数也都是对象,甚至连常量都被当作对象来对待。这意味着什么?Ruby语言提供了这样的一种机制,将数据和函数封装到对象里,实现了一个类到另一个类的继承机制;

(2)一切都是开放的。Ruby语言的面向对象是完全开放的。例如,可以在一个类中随意增加方法,即使在执行期也可以如此。这个内容将会在第5章详细说明;

(3)一切都可以混合。Ruby语言被有意设计成单继承模式。但是它具有模块的概念,模块是方法的集合,可以在一个类中引入任何一个模块从而自由地使用模块内的方法。这比复杂的、不常使用的多继承模式更加清晰明了。这就是非常有用的混入(Mix-In);

(4)一切都可以被动态载入。类可以在运行时重定义自己,也可以在运行时继承或取消继承;

(5)一切都可以被使用。使用被称为“保留字(reserved word)”的标识符是完全没有问题的,只要保证语法分析器不会遇到有歧义的情况就行;

(6)一切都是简单明了和直观的。Ruby以创新的方式使用大小写字母以及特殊符号。返回逻辑值的函数名称通常都以问号结尾;修改数据的函数名称带有惊叹号;所有常量都以大写字母开头;所有对象的属性开头都以符号“@”标记;以符号“$”开头的一定是全局变量;以符号“@@”开头的是类变量,等等;

(7)关注一切细节。Ruby语言提供了丰富的同义词和别名。如:数组或字符串的大小既可以用函数“size”也可以用函数“length”。对于范围(range),既可以用“begin”和“end”,也可以用“first”和“last”;

(8)一切都在按照规则行事。Ruby语言几乎没有违反自身规则的例外情况。Ruby语言的语法和语义比大多数语言更具自我完备性(self-consistent),且其语法和语义也比其他语言更有条理。一般来讲,每种规则都有例外情况,但Ruby语言的例外可能比你想象的要少;

(9)一切元素都有值。一切元素可以是一个对象或者一个逻辑表达式,甚至是一条语句。

3. 功能丰富

(1)具有异常处理机制。可以更少地与返回码纠缠;需要更少地嵌套条件语句;可以避免复杂混乱的代码设计——这让软件开发人员处理错误更加顺手;

(2)具有运算符重载(overloading)机制。Ruby语言会自动定义操作符的赋值(assignment)版本,比如说,如果定义了操作符“+”,那么就会自动得到操作符“+=”;

(3)具有自动内存管理机制。不再需要显式的回收内存(GC)的操作;

(4)具有调试器(debugger)代码功能;

(5)具有强大的字符串处理能力。如果想对字符串进行搜索、替换、修改、格式化、截断(trim)、分隔(delimit)、追加(interpose),或者字元化(tokenize)等操作,那么就可以使用Ruby语言的内建函数(即标准库函数)。如果内建函数不能满足要求,还可以借助内建函数来建构自己所需的函数。

4. 继承优秀传统

(1)支持正则表达式。正则表达式一直被认为是Unix领域的优秀特性,涉及的都是诸如grep和sed之类的复杂工具。现在越来越多的人认识到了这种超高级的字符串和文本操纵技巧中所蕴含的无比威力;

(2)支持Unix里面的文件和管道(pipes)概念;

(3)支持在C语言中广泛使用的函数printf的各种格式符号和功能;

(4)支持符合人们所习惯期待的方式。Ruby语言是非常直观的,只要你能想像到,Ruby语言就能提供。Ruby语言符合“最少诧异或惊讶”原则(Principle of Least Astonishment or Surprise);

(5)支持无“指针(pointer)”概念。没有指针运算,就没有语法和调试指针所带来的困扰。

Ruby是一种高度跨平台的语言,例如,可以在Linux上进行开发,而在Windows 2000/XP、Unix、Mac OS X、DOS等其他系统上运行;Ruby支持在任何系统上运行多线程程序,即使是在MS-DOS上;具有越来越完备的巨大标准库和越来越丰富的扩展库;它是开源项目,完全免费,有大量活跃的社区支持;在Windows上,可以加载动态软件库DLL;Ruby有一个真正智能的标记-清除(mark-sweep)垃圾回收器,它对Ruby中的所有对象均起作用。

1.1.4 Ruby程序实例

在本节中,将给出两个示范性程序。这两个程序分别是基于文件的Ruby程序和基于交互工具irb的Ruby程序。

基于文件的Ruby程序清单,见代码清单1-1。该程序的目的是在计算机的标准输出设备上输出字符“Hello World!”。虽然该程序只有短短的一条命令,但是,它确确实实是本书中所给出的第一个Ruby程序,使我们进一步体会到了Ruby语言的简洁性。

代码清单1-1第一个Ruby程序

puts "Hello, world!"

第二个程序的目的是向人们展示Ruby语言的整数可以有多大(见代码清单1-2)。在程序清单中,大多数程序代码是为了说明Ruby的无限精度而特意编写的。

看看变量a的返回值,够大了吧!其中符号“irb(main):019:0>”是交互工具irb的提示符,其后的“a=1”是Ruby程序代码,按回车键后,在新的一行以符号“=>”开始的行是上一行代码的输出结果。这里需要着重说明代码“365.times{ a, b = a*b, b+1 }”的含义。这行代码其实是一个循环语句,一共循环了365次。整个语句的含义是:计算从1到365之间所有自然数的连乘之积。需要注意的是随变量a的数字增大,其所属的类也在改变。在这个循环中,只有一行代码“a, b = a* b,b+1”,但是却在同时为a和b两个变量进行赋值,相当于代码:“ a =a*b; b = b+1”。请特别注意前面两个式子中间使用的分隔符号:逗号“,”和分号“;”。因为代码“a, b = a*b, b+1”中的分隔符号是逗号“,”,而不是分号“;”,所以千万不要把这个语句理解成:“a; b = a*b; b+1”。如果这样理解,这个赋值语句就变成了三条语句了。

代码清单1-2大数程序代码

irb(main):019:0> a=1【回车键】
=> 1
irb(main):020:0> b=1【回车键】
=> 1
irb(main):021:0> 365.times{ a,b = a*b,b+1 }【回车键】【不空格继续】
=> 365
irb(main):022:0> a【回车键】
=>2510412867555873229292944374881202770516552026987607976687259519【不空格继续】
396138220011093741966601800900025416937617231436098232866070807112【不空格继续】
336997985344536791065387238359970435553274093767809149142944086431【不空格继续】
604692507451013484702554601409800590796554104119549610531188617337【不空格继续】
343514551719328276084775588229169021353912347918627470151939680850【不空格继续】
494072260703300124632839880055048742799987669041697343786107818534【不空格继续】
466796687151104965388813013683619901052918005612584454948864861768【不空格继续】
291582634756414899098413806780999960468748814673483734069935983879【不空格继续】
112499595758453887361666153309325355125684505604638873812970295138【不空格继续】
115186141368892298651000544094394301469924411255575527914076049276【不空格继续】
425374025041039105642197900328960000000000000000000000000000000000【不空格继续】
0000000000000000000000000000000000000000000000000000000
irb(main):023:0> b【回车键】
=> 366
irb(main):024:0>exit【回车键

1.1.5 什么是JRuby语言

什么是JRuby?按照对JRuby的解释,JRuby语言是用Java语言对Ruby语言解释器所进行的再造过程(JRuby is the effort to recreate the Ruby(http://www.ruby-lang.org)interpreter in Java)。

JRuby语言官方网站是这样解释JRuby的:JRuby是一个100%用Java语言实现的Ruby程序开发语言。这就是说,JRuby是脚本语言Ruby解释器的Java实现。这意味着JRuby解释器是用纯Java语言重新编写的Ruby解释器。

JRuby解释器的目标之一就是100%实现原来用C语言实现的Ruby解释器的功能,并使其能充分利用已有的、成熟的Java资源。从不断正式发布的版本中可以看出,与Ruby的兼容性确实是一个基本的追求目标,所以,不是所有的Ruby软件包都可以在JRuby语言中直接被使用。

自从2006年7月5日第一个JRuby语言版本0.9.0被发布以来,JRuby版本已经经历了多次更新,其中的变化是巨大的,目前能够下载的稳定发行版本是1.0.3(http://dist.codehaus.org/jruby/),本书所使用的版本是目前最新版本1.1。JRuby语言版本1.1也将是自JRuby语言发布以来的一个重要的版本。中间发布的版本见表1-1。

表1-1 JRuby语言版本

不难发现,最多间隔4个月就发行一个版本,而且后面发行版本的速度越来越快,并且越是后面发行的版本,其与Ruby高版本的兼容性和效率就越好。譬如:JRuby 0.9.9版本的目标之一就定位在能够和Ruby1.8.4很好地兼容。另一个关注的焦点是性能:JRuby0.9.9比0.9.8版本要快40%。而JRuby团队使用的兼容性标准之一是:能够准确无误地运行Rails应用。除了官方的Ruby语言实现之外,JRuby语言也是目前唯一能够运行Rails应用软件框架的语言。JRuby核心开发者之一Ola Bini对于JRuby与Ruby1.8.4的兼容性表示满意,他说,“看起来一切兼容得都很好,几乎所有用Ruby1.8编写的应用都可以完美地运行。”

JRuby 1.0.0是JRuby项目的一个主要的里程碑版本。1.0.0的主要目标是解决Ruby的兼容性问题。

JRuby 1.0 is a major milestone for our project. Our main goal for 1.0 has been Ruby compatibility. We feel this goal has been reached. When we see companies like ThoughtWorks offering commercial JRuby support; we know this goal has been reached.

——摘自http://jruby.codehaus.org/

1.1.6 JRuby程序实例

为了便于与Ruby进行比较,这里给出两个JRuby语言程序实例,一个是基于交互工具jirb的JRuby语言程序,另外一个是基于文件的JRuby语言程序。

先考察一下最简单的JRuby语言程序,见代码清单1-3。在DOS窗口下启动交互工具jirb,该工具的执行命令就是jirb。在出现提示符以后,就输入代码清单1-3中所示的程序代码。其中,第1行代码说明本程序需要使用Java语言的软件包,输入程序代码完成后,按回车键。由于本程序并没有使用任何的Java语言包,所以这条语句是可以省略的。第2行代码是标准的Ruby语言代码。第3行代码(也可以使用“quit”)是退出该交互工具jirb。

代码清单1-3基于jirb工具的JRuby语言程序

require 'java'【回车键】
puts "Hello, world!"【回车键】
exit【回车键

第二个程序的代码,见代码清单1-4。将此程序以first_jruby.rb为文件名并且以utf-8编码保存。然后运行该程序,其输出结果见代码清单1-5所示。在这一程序中,使用了Java语言的标准软件包java.lang.System,就可以得到正确的中文显示。如果使用Ruby语言的函数puts就无法正确显示中文信息。需要指出的是,这里使用DOS窗口的当前代码编码GBK。如果DOS窗口代码编码(如GBK)与文件编码(如没有BOM的UTF-8)不符,系统命令(如cat)也会出现无法正确显示中文信息的状况,见图1-1的命令cat。对此的详细介绍将会在第4章中说明。

代码清单1-4基于文件的JRuby语言程序first_jruby.rb代码

require 'java'
include_class 'java.lang.System'
System.out.println "世界,您好!"

代码清单1-5基于文件的JRuby语言程序first_jruby.rb输出结果

E:\jruby_work\ch01>jruby first_jruby.rb
世界,您好!

图1-1 JRuby语言程序first_jruby.rb的屏幕输出结果