Ruby是起源于日本的编程语言。近年来,特别是因为在Web开发方面的效率很高,Ruby引起了全世界的关注,它的应用范围也扩展到了很多企业领域。

作为一门编程语言,Ruby正在被越来越多的人所了解,而作为一介工程师的我,松本行弘,刚开始的时候并没有想过“让全世界的人都来用它”或者“这下子可以大赚一笔了”,一个仅仅是从兴趣开始的项目却在不知不觉中发展成了如今的样子。

当然了,作为一种兴趣,开发Ruby并不是我的本职工作,我是把它作为一个自由软件来开发的。但是世事弄人,现在开发Ruby竟然变成我的本职工作了,想想也有些不可思议。

“你为什么开发Ruby?”每当有人这样问我 的时候,我想,最合适的回答应该就像Linux的开发者Linus Torvalds对“为什么开发Linux”的回答一样吧。

“因为它给我带来了快乐。”

当我还是一个高中生,刚刚开始学习编程的时候,不知何故,就开始对编程语言产生了兴趣。

周围很多喜欢计算机 的人,有的是“想开发游戏”,有的是“想用它来做计算”,等等,都是“想用计算机来做些什么”。而我呢,则对“要用什么编程语言来开发”、“用什么语言开发更快乐”有很大的兴趣。

高中的时候,自己并不具备开发一种编程语言所必需的技术、知识,而且当时也没有计算机。但是,我看了很多编程语言类的书籍和杂志,知道了“还有像Lisp这样优秀的编程语言”、“Smalltalk是面向对象设计的”,等等,在这些方面很着迷。上大学时就自然而然地选修了计算机语言研究的专业。10年后,通过开发Ruby实现了自己的梦想。

从1993年开始开发Ruby到现在已经过去16年了。在这么久的时间里,我从未因为设计Ruby而感到过厌烦。开发编程语言真是一件非常有意思的事情。编程语言的重要性

为什么会这么喜欢编程语言?我自己也说不清。至少,我知道编程语言是非常重要的。

最根本的理由是:语言乃人类思考的本质。在地球上,没有任何超越人类智慧的生物,也只有人类能够使用语言。所以,正是因为语言,才造成了人类和别的生物的区别。正是因为语言,人和人之间才能传递知识和交流,才能做深入的思考。如果没有了语言,人类和别的动物也就不会有太大的区别了。

在语言学领域里,有一个Sapir-Whirf假说,认为语言可以影响说话者的思想。也就是说,因为语言的不同,所以造成了思想的不同。人类的自然语言是不是像这个假说一样,我不是很清楚 ,但是我觉得计算机语言很符合这个假说。也就是说,程序员由于使用的编程语言不同,他的思考方法和编写出来的代码都会受到编程语言的很大影响。

也可以这么说,如果我们选择了好的编程语言的话,那么成为好程序员的可能性就会大很多。

20年来一直被奉为名著的《人月神话》的作者Frederick P.Brooks说过,一个程序员,不管他使用什么编程语言,他在一定的时间里编写的程序行数是一定的。如果真是这样的话,如果一个程序员一天可以写500行程序的话,那么不论他用汇编、C,还是Ruby,那么他一天都应该可以写500行程序。

但是,汇编的500行程序和Ruby的500行程序所能做的事情是有天壤之别的。程序员根据所选择编程语言的不同,他的开发效率就会有10倍、100倍,甚至1000倍的差别。

由于低价格化和高性能化,计算机现在已经很普及了。现在基本上各个领域都使用了计算机,但如果没有计算机软件,那么计算机这个盒子恐怕一点用都没有。而谈到软件开发,就要求能够用更少的成本,更短的时间,开发出更多的软件。

需要开发的软件越来越多,但是开发成本却有限,所以对于开发效率的要求就很高。编程语言就成了解决这个矛盾的重要工具。Ruby的原则

Ruby本来是我因为兴趣而开发的。因为对多种编程语言都很感兴趣,我广泛对比了各种编程语言,哪些特性好,哪些特性没什么用,等等,都一一进行了比较、选择,最终把一些好的特性都吸收到了Ruby编程语言之中。

如果什么都不考虑地去吸收的话,那么这种编程语言只会变成过去的编程语言的翻版,从而失去它作为一种新的编程语言的存在价值。

编程语言的设计是很困难的,需要仔细斟酌。值得高兴的是,Ruby的设计很成功,很多人都对Ruby给出了很好的评价。

那么,Ruby编程语言的设计原则是什么呢?

Ruby编程语言的设计目标是,让作为语言设计者的我能够轻松编程,进而提高开发效率。

根据这个目标,我制定了以下3个设计原则。 简洁性 扩展性 稳定性

关于这些原则,下面分别加以说明。简洁性

以Lisp编程语言为基础而开发的商业软件Viaweb被Yahoo收购后,Viaweb的作者Paul Graham也成了大富豪。最近他又成了知名的技术专栏作家,他写了一篇文章就叫“简洁就是力量” 。

他还撰写了很多拥护Lisp编程语言的文章,在这些文章中他提到,编程语言在这半个世纪以来是向着简洁化的方向发展的,从程序的简洁程度就可以看出一门编程语言本身的能力。上面提到的Brooks也持同样的观点。

随着编程语言的进化,程序员已经可以更简单、更抽象地编程了,这是很大的进步。另外随着计算机性能的提高,以前在编程语言里实现不了的事情现在也可以做到了。

用面向对象编程语言举一个例子。把数据和方法作为对象来看待是面向对象的设计方法。但是在执行一个方法时需要做额外的判断处理,而在以前,由于计算机的性能低,这种额外的处理是实现不了的。

而现在,由于计算机性能大大提高,只要可以提高软件开发效率,多少浪费一些计算机资源也无所谓了。

再举另外一些例子。比如内存管理,不用的内存现在可用垃圾收集器自动释放,而不用程序员自己去释放了。变量和表达式的类型检查,在执行时已经可以自动检查,而不用在编译时检查了。

让我们看一个关于斐波纳契(Fibonacci)数的例子。图1-1是用Java程序来计算斐波纳契数的。算法有很多种,我们用最常用的递归算法来实现。

图1-2是基于完全一样的实现方法,用Ruby编程语言写的程序;算法完全一样。和Java程序比较的话,可以看到构造完全一样,但是程序就更简洁。Ruby不做明确的数据类型定义,不必要的声明都可以省略。所以,程序就非常简洁了。

算法的教科书总是用模拟语言来描述算法。如果像这样用实际的编程语言来描述算法,那么像类型定义这样的非本质代码就会占很多行,会让人不能专心于算法。

但是,如果把模拟编程语言中非本质的东西去掉,只保留描述算法的部分就直接可以运行的话,那么这种编程语言不就是最好的吗?Ruby的目标就是成为开发效率高,“能直接运行的模拟编程语言”。扩展性

下一个设计原则是“扩展性”。编程语言作为一个软件开发工具,最大的特征就是要实现的功能事先没有限制。“如果想做就可以做到”,这听起来像小孩子说的话,但在编程语言的世界里,真的就像这句话所说的一样。不管在什么领域,不管做什么处理,只要用一种编程语言编写出了程序,我们就可以说这种编程语言适用于这一领域。而且,涉及领域之广会远远超出我们当初的预想。

1999年,最初的关于Ruby的书籍《面向对象脚本语言Ruby》出版的时候,我在里面写到了“Ruby不适合的领域”,包括“以数值计算为主的程序”和“数万行的大型程序”。

但是几年后,规模达几万行、几十万行的Ruby程序被开发出来了。气象数据分析,乃至生物领域中也用到了Ruby。现在,美国国家海洋和大气局(NOAA,National Oceanic and Atmospheric Administration)与国家航空和航天局(NASA,National Aeronautics and Space Administration)也在不同的系统中运用了Ruby。

情况就是这样,编程语言开发者事先并不知道这种编程语言都会用来开发什么,都会在哪些领域中应用。所以,编程语言的扩展性非常重要。

实现扩展性的一个重要方法是抽象化。抽象化是指把数据和要做的处理都封装起来,就像一个黑盒子,我们不知道它的内部是怎么实现的,但是可以用它。

以前的编程语言在抽象化方面是很弱的,要做什么处理首先要了解很多编程语言的细节。而很多面向对象或者函数式的现代编程语言,都在抽象化方面做得很好。

Ruby也不例外。Ruby从刚开始设计时就用了面向对象的设计方法,数据和处理的抽象化提高了它的开发效率。我在1993年设计Ruby时,在脚本编程语言中采用面向对象思想的还很少,用类库方式来提供编程语言的就更少了。所以现在Ruby的成功,说明当时采用面向对象方法的判断是正确的。

Ruby的扩展性不仅仅体现在这些方面。比如Ruby以块这种明白易懂的形式给程序员提供了相当于Lisp高阶函数的特性,使“普通的程序员”也能够通过自定义来实现控制结构的高阶函数扩展。又比如已有类的扩展特性,虽然有一定的危险性,但是程序却可以非常灵活地扩展。关于这些面向对象、程序块、类扩展特性的内容,后面的章节还会详细介绍。

这些特性的共同点是,它们都表明了编程语言让程序员最大限度地获得了扩展能力。编程语言不是从安全性角度考虑以减少程序员犯错误,而是在程序员自己负责的前提下为他提供最大限度发挥能力的灵活性。我作为Ruby的设计者,也是Ruby的最初用户,这种设计的结果表明,Ruby看重的不是明哲保身,而是如何最大限度地发挥程序员自身的能力。

关于扩展性,有一点是不能忽视的,即“不要因为想当然而加入无谓的限制”。比如说,刚开始开发Unicode时,开发者想当然地认为16位(65 535个字符)就足够容纳世界上所有文字了;同样,Y2K问题也是因为想当然地认为用2位表示日期就够了才导致的。从某种角度说,编程的历史就是因为想当然而失败的历史。而Ruby对整数范围也不做任何限定,尽最大努力排除“想当然”。稳定性

虽然Ruby非常重视扩展性,但是对一个特性,尽管明知道它能带来巨大的扩展性,也一直都将其拒之门外。那就是宏,特别Lisp风格的宏。

宏可以替换掉原有的程序,给原有的程序加入新的功能。如果有了宏,不管是控制结构,还是赋值,都可以随心所欲地进行扩展。事实上,Lisp编程语言提供的控制结构很大一部分都是用宏来定义的。

所谓Lisp流,其语言核心部分仅仅提供极为有限的特性和构造,其余的控制结构都是在编译时通过用宏来组装其核心特性来实现的。这也就意味着,由于有了这种无与伦比的扩展性,只要掌握了Lisp基本语法S式(从本质上讲就是括号表达式),就可以开发出千奇百怪的语言。Common Lisp的读取宏提供了在读取S式的同时进行语法变换的功能,这就在实际上摆脱了S式的束缚,任何语法的语言都可以用Lisp来实现。

那么,至于我为什么拒绝在Ruby中引入Lisp那样的宏,那是因为,如果在编程语言中引入宏的话,活用宏的程序就会像是用完全不同的专门编程语言编写出来的一样。比如说Lisp就经常有这样的现象,活用宏编写的程序A和程序B,只有很少一部分是共通的,而从语法到词汇都各不相同,完全像是用不同的编程语言写的。

对程序员来说,程序的开发效率固然很重要,但是写出的程序是否具有很高的可读性也非常重要。从整体来看,程序员读程序的时间可能比写程序的时间还长。读程序包括为理解程序的功能去读,或者是为维护程序去读,或者是为调试程序去读。

编程语言的语法是解读程序的路标。也就是说,我们可以不用追究程序或库提供的类和方法的详细功能,但是,“这里调用了函数”,“这里有判断分支”,等等,这些基本的“常识”在我们读程序时很重要。

但是一旦引入了宏定义,这一常识就不再适用了。看起来像是方法调用,而实际上可能是控制结构,也可能是赋值,也可能有非常严重的副作用,这就需要我们去查阅每个函数和方法的文档,解读程序就会变得相当困难。

当然了,我知道世界上有很多Lisp程序员并不受此之累,他们正是通过面向特定程序定制语言而最大限度地提高了开发效率。但是在我个人看来,他们只是极少数的一部分程序员。

我相信,作为在世界上广泛使用的编程语言,应该有像不随风飘荡的灯芯那样稳定的语法。一切皆因兴趣

当然,Ruby不是世界上唯一的编程语言,也不能说它是最好的编程语言。各种各样的编程语言可以在不同的领域中应用,各有所长。我自己以及其他Ruby程序员,用Ruby开发效率很高,所以“觉得Ruby最为得心应手”。当然用惯了Python或者Lisp的程序员,他们会觉得那些编程语言是最好的。

不管怎么说,编程语言存在的目的是让人用它来开发程序,并且尽量能提高开发效率。这样的话,才能让人在开发中体会到编程的乐趣。

我在海外讲演的时候和很多人交流过使用Ruby的感想,比较有代表性的是“用Ruby开发很快乐,谢谢!”

是啊,程序开发本来就是一件很快乐、很刺激和很有创造性的事情。想起中学的时候,用功能不强的BASIC编程语言开发,当时也是很快乐的。当然,工作中会有很多的限制和困难,编程也并不都是一直快乐的,这也是世之常情。

Ruby能够提供很高的开发效率,让我们在工作中摆脱很多困难和烦恼,这也是我开发Ruby的目的之一吧。