人们出于各种目的学习自然语言。学母语是为了生存,为了日常生活中与人正常交往。学外语的目的可就五花八门了。有时候,为了未来的职业发展或为了适应日益变化的生活环境,你不得不学习外语;但有时候,你决心征服一门外语,不是因为不得不这么做,而是因为发自内心地想学。外语能带你领略一片未曾见过的风景。你甚至可能领悟一个道理:每学一门新的语言,思维方式都会发生改变。
编程语言亦是如此。在这本书中,我将为你介绍七门各不相同的语言。不过,我不会像你的妈妈那样将吃的直接喂到你嘴边。我更愿意做你的导游,带你体验一次启迪心智之旅,并由此改变你看待编程的视角。写这书的目的不是让你成为专家,而是教会你比“Hello, World”更实用的知识。
1.1 不走寻常路
假如我想新学一门编程语言或一种编程框架,一般会找一篇速成互动教程看看。因为这类教程中,先做什么、后做什么都已精心设计好。通过它们,我们可以更容易体会语言的妙处所在。当然,扔掉教程,直接动手实践也未尝不可,但说白了,我就是想尽快发现语言的动人心弦之处,尽快对它的语法糖和核心概念有个大体印象。
然而多数情况下,我找不到称心如意的教程。受到篇幅限制,那些教程往往只介绍各门语言间相去无几的皮毛。而这些皮毛,我又早已熟知。若想领会一门语言的精髓,它可就无能为力了。我想要的是那种痛快淋漓、深入探索语言本质的感觉。
本书将会给你这种感觉。不是一次,而是七次。你将从书中找到以下问题的答案。
语言的类型模型是什么?强类型(Java)或弱类型(C语言),静态类型(Java)或动态类型(Ruby)。本书侧重于介绍强类型语言,但各种静态类型和动态类型语言也都有所涉及。你将看到,语言在类型模型间的权衡会对开发者产生何种影响。语言的类型模型会改变你对问题的处理方式,还会控制语言的运行方式。就类型模型而言,书中的每门语言都堪称独树一帜。
语言的编程范型是什么?是面向对象(object-oriented,OO)、函数式、过程式,还是它们的综合体?本书介绍的语言涵盖了4种编程范型,有些语言还由几种范型组合而成。你将看到一门基于逻辑的编程语言(Prolog)、两门完全支持面向对象思想的语言(Ruby和Scala)、四门带有函数式特性的语言(Scala、Erlang、Clojure和Haskell)及一门原型语言(Io)。这里有Scala这样的多范型(multiparadigm)语言,也有Clojure这种多方法(multimethod)语言,后者甚至允许你实现自定义范型。本书最重要的任务之一,就是学习新的编程范型。
怎样和语言交互?语言可编译也可解释,可以有虚拟机也可以没有。在本书中,如果某门语言带交互命令行,将先通过交互命令行探索这门语言,当我们处理规模较大的项目时,还会转而采用文件编程。我们接触的项目不会特别大,因此无需深入研究打包(packaging)模型。
语言的判断结构(decision construct)和核心数据结构是什么?或许你会惊讶,在作判断时,居然如此多的语言都用到了与if和while的各种变型都不相同的结构。你会见识到Erlang的模式匹配,还有Prolog的合一(unification)。至于数据结构,集合(collection)在任何语言中都扮演着至关重要的角色。对Smalltalk和Lisp这类语言,集合刻画了语言特征,而在C++和Java等语言中,集合更可谓无所不在,它们决定着用户体验,若没了它们,语言势必成为一盘散沙。因此,无论用哪一类语言,都必须全面、透彻地理解集合。
哪些核心特性让这门语言与众不同?有些语言支持并发编程的高级特性,有些语言提供独一无二的高级结构,比如Clojure的宏(marco)和Io的消息解释(message interpretation);有些语言包含性能强劲的虚拟机,如Erlang的BEAM,它能让 Erlang构建的容错分布式系统远远快于其他语言;有些语言提供专门针对特定问题的编程模型,比如利用逻辑规则解决约束问题。
就算这些问题全被你弄个一清二楚,你仍然成不了语言专家,哪怕只是其中一门语言。但你会明白,这几门语言各自拥有哪些独门绝技。下面,我们先看看本书介绍了哪几门语言。
1.2 语言
从众多语言中,挑出本书包含的几门语言,这一过程也许不像你想得那么复杂。我们只不过发了些调查问卷,向本书的潜在读者请教了一番。调查数据汇总上来时,有八门语言入选希望最大。不过,我先把JavaScript“踢”了出去,因为它实在是过于热门了,取而代之的是原型语言中热门程度仅次于JavaScript的Io。随后,我又把Python“踢”了出去,因为我只想给面向对象语言一个名额,而Ruby的票数多于Python。同时,这也给一个出人意料的候选者让出了位置——名单上位列前十的Prolog。下面,我给出成功入围本书的最终名单以及挑选它们的理由。
Ruby。这门面向对象语言高票当选,因为它不仅好用,而且好读。我曾经考虑过不介绍任何一门面向对象语言,但我又想在其他编程范型与面向对象编程之间作一些比较,因此,至少介绍一门面向对象语言还是有必要的。相比于大多数程序员的日常用法,我想把它挖掘得更深入一些,以揭示设计者的良苦用心。我最终决定重点介绍Ruby元编程(metaprogramming),因为它可以用来扩展Ruby的语法。对于Ruby榜上有名的结果,我还是相当认可的。
Io。和Prolog一样,Io也是本书颇具争议的语言。它虽与商业成功无缘,但其兼具简单性和语法一致性的并发结构,却是十分重要的思想。它的最简语法(minimal syntax)功能强大,与Lisp的相似性也颇能给人留下几分印象。Io不仅和JavaScript一样同为原型语言,还有着独一无二、韵味无穷的消息分发机制,因此在众多编程语言之中,它也占有小小的一席之地。
Prolog。没错,Prolog年事已高,但它仍然威力无穷。它能轻松解出数独问题,这着实让我大开眼界。用Java或C语言时,有些难题我殚精竭虑方能解决,用Prolog却能干净利落地搞定。承蒙Erlang发明者Joe Armstrong出手相助,我得以深刻体会到Prolog之妙,而且也正是深受Prolog影响,Erlang才得以问世。如果你此前从未用过Prolog,我保证,它定会带给你惊喜。
Scala。作为运行于Java虚拟机上的新一代语言,Scala为Java系统引入了强大的函数式思想,同时也并未丢弃面向对象编程。回顾历史,我发现C++和Scala有着惊人的相似之处,因为从过程式编程过渡到面向对象编程期间,C++同样起到了举足轻重的作用。当你真正融入Scala社区之后,你就会明白,为什么对于函数式语言程序员来说,Scala是异端邪说,而对于Java开发者来说,Scala是天降福音。
Erlang。作为名单上历史最悠久的语言之一,Erlang不仅是一门函数式语言,而且在并发、分布式编程、容错等诸多方面都有优异表现,真是想不火都难。CouchDB(新兴的基于云的数据库)的创始人就选择了Erlang,并且义无反顾地一直用它,只要花上点时间了解这门分布式语言,你就会明白原因所在。在Erlang帮助下,设计带有并发、分布式、容错等特征的应用程序将变得无比简单。
Clojure。这又是一门Java虚拟机语言,但正是这门Lisp方言,彻底颠覆了我们在Java虚拟机上并发编程的思考方式。它是本书唯一在版本数据库中使用同一种策略管理并发的语言。作为Lisp方言,Clojure或许拥有本书所有语言中最灵活的编程模型,因此绝不缺乏号召力。与其他Lisp方言不同的是,它不会带那么多括号,还有众多Java库和在各平台上的广泛部署作为坚强后盾。
Haskell。它是本书唯一的纯函数式语言,这也意味着,它根本不存在可变状态:只要使用相同的输入参数,去调用相同的函数,就会返回相同的输出。在所有强类型语言中,Haskell拥有最令人称羡的类型模型。和Prolog一样,它也需要你花一些时间理解,但你得到的回报绝对物超所值。
如果名单上没有你钟爱的语言,我深感抱歉。老实说,还真有语言狂热分子给我发过好几封恐吓信。在本节开始提到的民意调查中,我们总共列出了几十门语言。我挑的这几门语言未必是其中最出色的,但它们特点突出、个性鲜明,都具有重要的学习价值。
1.3 谁应该买这本书
如果你是一名称职的程序员,想提高自己的编程水平,那你应该买这本书。这话说来有几分含糊,请容我解释一二。
1.3.1 学会如何学习
Dave Thomas是Pragmatic Bookshelf出版社的创始人之一,我这本书就是他们出版的。他每年都鼓励数以千计的学生去学一门新语言。学过各式各样的语言后,你最少也能挑出一门得心应手的语言用用,并把其他语言的精华思想融入到这门语言的代码中去。
这本书的写作过程已经深刻影响了我所编写的Ruby代码。相比于过去,我编写的Ruby代码中,函数式味道更加浓郁,且因重复部分变少而增加了可读性。我在代码中尽量缩减了可变变量的数量,还利用代码块和高阶函数写出了更有效的代码。此外,我也用到一些不大符合Ruby惯例,但会让代码更简明的技巧。
学语言最理想的情况,是由它引领你踏上一条崭新的职业道路。每十年左右,编程范型都会发生一次变革。几年前,我感觉Java越来越别扭,于是就去体验了一把Ruby,看看怎么用它进行Web开发。经过几个过渡项目的磨合,我开始重点发展Ruby方向上的业务,从此彻底告别Java。我的Ruby生涯始于玩票,但随之而来的,却是事业的不断发展壮大。
1.3.2 乱世英雄
说到本书读者,他们大概还没那么老,不至于经历过上一次编程范型的更新换代。回想刚换到面向对象编程那会儿,我们遇到过好几次挫折,不过话说回来,当时的结构化编程范型已完全无法应付现代Web应用的复杂性。Java编程语言的成功为Web应用开发打了一针强心剂,也因此奠定了面向对象编程这种新编程范型的地位。不过,当时很多开发者已深深陷入了过时技术的桎梏中。他们若想顺利过渡到新编程范型,必须由内到外重新打造思考编程的方式、手头用于开发的工具、设计应用程序的方法等才行。
现在,我们可能正身处又一次变革的进程当中。这一次变革,新的计算机设计架构将成为主要推动力。在本书的七门语言中,五门都拥有强大的并发模型(Ruby和Prolog不在其列)。无论你用的编程语言会不会一夜之间物是人非,我敢向你保证,在应对这场变革之时,本书介绍的所有语言都能拿出令人信服的策略。看看Io对future的实现、Scala的actor、Erlang的“任其崩溃”(let it crash)哲学,再看看Haskell如何把可变状态抛到九霄云外、Clojure如何利用版本控制解决最为棘手的并发问题,你就会相信这一点。
当然,那些看似平凡的语言也不可小觑,它们带来的启示同样让人啧啧称奇。Erlang这门用于多个云数据库后台的语言就是个极佳的例子。正是以Prolog为基础,Joe Armstrong博士创立了这门语言 。
1.4 谁不应该买这本书
如果你没有读过本节,或读过但不认同其中观点,那你不应该买这本书。买这本书等于跟我做了笔买卖:你认可我把重点放在编程语言本身而非详尽的安装过程上,我承诺在有限时间内尽可能多地授业解惑。你要学会利用Google搜索那些细枝末节,可别指望我会帮你解决各种安装问题。如此一来,我才有空间深入挖掘语言本身,而你在读过本书后,也才能了解更多语言方面的细节。
请务必明白,这七门语言,无论教还是学,对我们而言都是一个宏伟目标。作为读者,你的脑袋必须多腾出点地方,以容纳七种不同的语法风格、四种编程范型、四十年语言开发的宝贵经验;作为作者,我必须尽量全面地涵盖各个主题,以便让你更好地理解语言。为了写好这本书,我老早就学过了这七门语言中的几门,但若想完美地兼顾每门语言所有最重要的细节,还需要一些化繁为简的本事才行。
1.4.1 超越语法
想真正理解语言设计者的思路,就必须有超越基本语法的觉悟。这意味着,你不能仅仅停留在编写“Hello, World”这种普通代码,甚至斐波那契数列代码的水平。如果是Ruby,你得会写一些元编程代码;如果是Prolog,你必须会解决完整的数独问题;如果是Erlang,你要懂得如何写一个监控程序,这程序不仅能检测崩溃进程,还能启动另一进程以接替崩溃进程的工作,或将崩溃进程的相关信息告知用户。
在地带你超越语法之前,我要先向你作个承诺,同时也不得不作个让步。承诺是:决不会浅尝辄止、敷衍了事;让步是:无法像专业语言书籍那样涵盖所有基础知识。我几乎没有涉及异常处理,除非它是哪一门语言的基本特性;我也没有详细介绍包模型,因为我们做的都是小项目,没有必要用到打包模型;还有,不少原始类型(primitive)我也只字未提,因为解决本书提出的基本问题时,用不到的原始类型自然不必提到。
1.4.2 不是安装指南
写这书最大的挑战来自于平台。我与各种书的不少读者都有过直接接触,他们所用的平台包括三种Windows平台、OS X以及至少五种Unix系统。我也在各大留言板上看过数不胜数的平台之争。把七门语言安装到七种平台上,这别说一位作者,就算多位作者合著,估计也是无解难题。我无意解决七门语言的安装问题,所以就不费那精力去琢磨多平台了。
我猜你不会有兴趣读一份老掉牙的安装指南。语言和平台都在不断发生变化。我只要告诉你去哪里安装语言、我用的是什么版本就够了。这样你就可以和大家一样,照着最新的安装指南去做。一步步地教你安装语言真没什么必要。
1.4.3 不是编程参考
为保证本书质量,我们尽最大努力对书中代码进行了审阅,其中一部分还有幸请到了语言设计者亲自审阅。在经历出版前的层层严格审阅之后,我确信,这些代码足以深刻阐释每一门语言的精髓。不过,当你自己试着上手用这七门语言编程时,我再怎么玩命,也不可能把一份全面的语言参考摆在你面前。请你多多谅解。关于这点,我想拿平时会话所用的语言打个比方。
观光旅游时学到的语言,和作为母语而熟知的语言相去甚远。我英语说得流畅自然,西班牙语却磕磕绊绊。还有三门语言,我也会说若干短语。我能在日本吃饭时点鱼,也能在意大利问人找洗手间。但我心知肚明的是,自己非母语的表达能力实在有限。说到编程,我的BASIC、C、C++、Java、C#、JavaScript、Ruby等几门语言都十分熟练。不甚熟练的语言也不少,其中还包括本书介绍的几门语言。说老实话,以我现在的水平,七门语言中有六门都不是非常得心应手。近五年当中,我一直全职编写Ruby代码,但说到其他语言,我是既说不出怎么用Io编个Web服务器,也说不出如何用Erlang编个数据库。
如果真去写一本这七门语言的参考大全,那我一定死得很惨。就算从中随便挑一门语言写编程指南,也至少会有咱们这本书差不多厚。我能提供各种材料,帮你轻松入门;也能带你体验每门语言的真实范例,让你亲眼见识它们的程序代码;还能尽量编译所有代码,确保它们正常运行。但如果你在试验这些语言时,也希望我能提供指导,那我真是心有余而力不足。
这七门语言都有非常优秀的支持社区,这也是我选择它们的原因之一。而且在每个习题环节,我还尽量保留了一个搜索语言相关资源的问题。用意很明显——让你学会自力更生。
1.4.4 严格督促
本书为你铺就的学习途径,较之网上那些20分钟教程可谓略胜一筹。我知道,你我同为善用Google之人,随便搜索书中某门语言的简明教程自是不在话下。不过本书的高明之处在于,它会带你踏上快速成长的互动之旅。你每周都会遇到一些小型的编程挑战和一个实战项目。解决它们虽非易事,但这既能增长你的见识,还可让你体验编程之乐。
如果你阅读本书时不做任何习题,那不过是对语法有了个粗浅认识。如果你在尝试独立解答习题之前,先去网上搜索答案,那也一样意味着不及格。你首先要有试着解答习题的主观愿望,同时也要充分认识到,有一小部分习题可能超出了你的能力范围。要知道,学会语法永远比学思考简单。
如果以上描述让你心惊胆战,我建议你放下这本书,换本别的书看看。对你来说,也许看七本不同的编程语言书会更轻松惬意。但是,如果你马上想到的是看这本书所能带来的回报——写出一手更漂亮的代码——并为此激动不已,那就别犹豫了,赶紧往下看吧。
1.5 最后一击
此时此刻,我真想对你说几句意义深远又让人热血沸腾的话,但千言万语汇成四个字——享受编程。
……
展开
★“为了了解更多的范例,提高编程水平,我读了很多相关的技术书,其中不乏让人拍案叫绝之作,本书即是一例。Bruce有丰富的学习经历和使用多种语言的经验,他把一些杰出的范例很好地组合到了一起,让读者从他的这些经验中有所斩获。我极力推荐!”
——Vankat Subramaniam博士,Agile Developer公司创始人,敏捷开发权威
★“看过这本书后,我解决问题的思路扩宽了,学习新语言的热情也被点燃了。”
——Travis Kaspar,Northrop Grumman公司软件工程师