本书由直接参与Scala开发的一线人员编写,因而对原理的解读和应用的把握更加值得信赖。本书面向具有一定编程经验的开发者,目标是让读者能够全面了解和掌握Scala编程语言的核心特性,并能够深入理解Scala这门语言在设计取舍背后的动因。即便是不直接使用Scala或从事一线编程工作的读者,也能从本书学到大量关于函数式和面向对象的编程概念和技巧。
Scala之父扛鼎巨著 来自语言设计者的精准|深邃|完整 基于2.12全面更新
推荐序
这本书可以说Scala语言里的圣经。很高兴高宇翔将它的第3版也翻译为了中文,对于国内的Scala爱好者来说真的是一个福音。
回想起七八年前,刚开始学习Scala时市场上还没有一本中文版的书。阅读英文版《Programming in Scala》的过程还是蛮费力的,即便我当时已经有很多年的Java编程经验。当时函数式编程的影响还比较弱,主流的编程风格还是命令式的(当然目前也依然是,但主流的编程语言里也开始越来越多地融入了函数式的风格),函数式编程里有很多陌生的概念是之前未曾了解过的,阅读的过程磕磕绊绊。
大概七年前《Scala编程》第1版发行的时候我立即去买了一本,相比英文版阅读速度有极大的提升。后来我陆陆续续地将这本书读过很多遍,每次都能有新的收获。
这七年来Scala的发展势头很猛,语言也在不断地调整,相比之下第1版的部分内容已经陈旧了,第3版的翻译让国内的Scala开发者可以更好地从中摄取知识和经验,即便你是Scala开发的老手也可以重温这本经典著作,一定会有新的体会。
或许对于毫无编程经验的初学者来说这本书并不适合作为你的第一本入门编程书,因为Scala本身是一门集大成者的语言,它多范式的风格将很多优秀的特性集成到了一起,具备很灵活的正交性。无编程经验的初学者未必能把握住。但是对于任何有好奇心的程序员来说,我认为它是你书架上必不可少的一本书。三位作者都是大师级人物,里面看似不经意的只言片语仔细体会的话也别有洞天。
三位大师在书中所说的很多内容,仔细揣摩,你会发现只是冰山一角,背后有更多可以深挖的内容。但这本书的定位也是面向普通的开发人员,大师们也保持得比较克制,不刻意流露一些复杂晦涩的概念,比如本书对流控、for表达式等有极其详尽的描述,但并不刻意提及Monad这样的术语,更多让开发可以去应用和实践它。大师们对偏理论的东西给出了一些线索,如果我们保持好奇心,可以顺着线索去探究编程语言背后庞大的理论体系。
对于一些语言爱好者,这本书也是一个重要的参考,我记得初次读完"组合子解析"(Combinator Parse)这一部分内容时非常震撼,居然可以用极其简短的代码实现一些非常复杂的解析器工作。对于想要实现自己的DSL来说实在是太轻松了。还有模式匹配部分,这本书也是我见过的讲解得最详细的一本书。还有面向对象设计等方面,原本觉得熟稔于心的东西也有必要重新思考一下。
总之,这本书值得反复阅读,带着好奇与思考,你会体验到与大师对话的乐趣。
—— 王宏江 挖财中间件负责人
译者序
这是一本很多人期待了近7年的书。
时光拉回到2010年的夏天,那个时候,Scala还是2.7.x的版本,Java还不支持lambda表达式。因为好奇心的驱使,一群不甘寂寞、不怕折腾的程序员,通过各种方式自学并开始实践Scala编程,慢慢地形成了小圈子。在国内的大小论坛和一些公开的技术会议上,大家也开始陆续听到关于这门编程语言的介绍和讲解。不过,成体系的中文资料非常少。也是在2010年,电子工业出版社引进了由Martin Odersky、Lex Spoon和Bill Venners合著的《Scala编程》中文版权,由黄海旭翻译,他是国内最早的一批Scala爱好者。同为爱好者的我,非常荣幸,参与了这本《Scala编程》部分章节的翻译。
那是一个Scala爆炸式增长的时期,各种开源项目层出不穷(著名的Apache Spark项目就是在这个时候诞生的)。Scala自身的版本迭代演进也很快,关于2.8版本的讨论和开发进展非常鼓舞人心。考虑到2.8相比之前的版本有了比较大的改进,作者们为了更好地普及Scala,《Scala编程》原书于2011年初推出了第2版,覆盖了2.8版本的特性。由于此时中文的《Scala编程》(第1版)刚出版不久,错过了引入更新的最佳时机,包括我在内的很多爱好者,开始了对这本中文书的更新版本的漫长等待。
在等待的过程中,我们共同见证了2012年的《快学Scala》、2014年的《深入理解Scala》、2015年的《Scala编程思想》和2016年的《Scala函数式编程》等多本Scala中文图书的面世。同样是这几年,Java 8正式发布,Scala也公布了2.12版本的线路图,全面拥抱Java 8。2016年5月,《Scala编程》原书第3版正式发售,内容覆盖2.12版本的新特性。当得知电子工业出版社最终确定引进《Scala编程》(第3版)的中文版权并邀请我翻译时,我个人非常激动:终于等来了这次更新。当然了,激动之余是忐忑:一方面翻译需要投入的心力和体力是巨大的;更为重要的是,自己能不能对得起这本书的分量,不要辜负了大家的期望。
说到这本书的分量,除了篇幅之外,我认为最值得一提的,是它不仅全面覆盖了Scala几乎所有的语言特性,还从语言开发者的视角,向我们介绍了这些语言特性和设计取舍背后的原因,以及要解决的问题。这是《Scala编程》跟其他林林总总的Scala图书最大的区别。从工具和工具书的角度,你也许会觉得:编程语言就是拿来干活儿的,一本编程语言的入门书,当然就是要把怎么用讲明白,让我高效地完成手中的工作,其他都是次要的。这里,我想给读者朋友们分享一个我自己的心得:语言除了表达外(让计算机和其他人类明白),更是思维的载体。学习一门编程语言,局部功利的因素当然有,但更多的,是通过这门语言,拓宽你的知识边界。语言是手段,不是目的。所以,不论你是否从事Scala编程工作,希望这本书,都能够带给你不一样的世界和认知。
序
这本书你真是选对了时候!采用Scala的团队和项目越来越多,我们的社区也在不断壮大,Scala相关的职位招聘也十分常见。不论你编程是因为兴趣还是工作(或两者皆有),Scala带给你的愉悦和生产力都难以拒绝。对我而言,编程真正的乐趣来自用简单、精巧的方案解决有意思的挑战。Scala的任务不仅让这件事成为可能,更让它充满乐趣。本书将告诉你Scala是如何做到这些的。
我从Scala 2.5开始接触这门编程语言,很快就被它的语法和概念的规则一致所吸引。当看到类型参数自己不能有类型参数这样的不规则情况出现时,我在2006年一次开发者大会上(战战兢兢地)走向Martin Odersky,毛遂自荐以实习生的身份参与Scala开发,去掉了这个限制。我的修改最终被采纳,Scala从2.7版本开始正式支持类型构造方法的多态(type constructor polymorphism)。从那时起,我参与了其他大部分编译器模块的开发。2012年,我从Martin的实验室读完博士后,加入了Typesafe的Scala小组。1也差不多是在那个时候,Scala发布了2.10,从实用偏学术的环境“毕业”,成长为适用于企业开发环境的一门强大的编程语言。
Scala 2.10是Scala发展过程中的拐点,从快节奏的基于学术研究的功能性版本发布,走向关注简单和加速在企业计算领域的落地。我们将注意力转到那些不会出现在论文中的问题,比如跨大版本的二进制兼容。为了保持稳定性和不断改进、完善平台的热望之间的平衡,我们正在往一个更小的核心类库这个方向努力,让它变得更稳定,同时让整个Scala平台继续进化。为此,我作为Scala技术领导的首个项目,便是在2.11中启动对Scala标准类库的模块化。
为减少变更频率,Typesafe还决定将类库和编译器重构升级安排在不同的版本。这一版《Scala编程》涵盖Scala 2.12版本,该版本是一次编译器升级,支持新的后端以及针对Java 8新特性的优化。为了更好的Java互调用,让用户享受到跟Java一样的来自JVM优化的好处,Scala将函数编译成跟Java 8一样的字节码。Scala的特质现在也同样编译成带有默认方法的Java接口。这两个编译器特性减少了之前版本Scala编译器需要完成的“魔法”,让我们更加贴近Java平台的原生表现,同时提升了编译速度和运行时性能,还让二进制兼容更加平滑!
Java 8平台的这些改进站在Scala的角度非常振奋人心,我们很高兴看到Java也踏上了Scala在十多年前引领的潮流。毫无疑问,Scala提供了更好的函数式编程体验,默认不可变、语句即表达式(在本书里很难找到return语句)、模式匹配、定义处的型变(Java的使用处型变让子函数的定义非常别扭),等等。这么说吧,函数式编程并不仅仅是支持lambda表达式这样的漂亮语法而已。
作为Scala这门编程语言的掌舵人,我们的目标是兼顾核心语言的开发和生态的建设。Scala之所以成功,离不开那些优秀的类库、出色的IDE和工具,离不开我们社区中那些友好的、乐于助人的成员们。我非常享受我在Scala的第一个十年(作为Scala的实现者),跟来自数不清的领域里的Scala程序员们一起感受快乐和鼓舞。
我热爱Scala编程,希望你也一样。代表Scala社区,欢迎你!
—— Andriaan Moors San Francisco, CA 2016年1月14日
引言
本书是Scala编程语言的教程,由直接参与Scala开发的人来编写。我们的目标是让读者通过本书,能够了解和掌握成为高产的Scala程序员需要知道的一切。书中的示例,除标记为2.12的之外,均能通过Scala 2.11.7编译,标记为2.12的示例需要Scala 2.12.0-M3(或更高版本)。
谁读本书
本书主要的目标读者是希望学习如何用Scala编程的人。如果你想在你的下一个项目中使用Scala,本书就是为你准备的。除此之外,本书对于那些想要学习新知识从而扩展自己眼界的程序员也同样有益。比方说,如果你是Java程序员,阅读本书,将让你接触到来自函数式编程领域和高阶面向对象领域的许多概念。我们相信,通过学习Scala,以及Scala背后的观念,将有助于你成为一名更好的程序员。
我们假定你拥有常规的编程知识。尽管Scala作为用于入门的编程语言并没有什么不妥,但是这本书并不适用于(从零开始)学习编程。
另一方面,阅读本书并不要求某项具体的编程语言的知识。我们当中大部分人都是在Java平台上使用Scala,但本书并不假定你了解Java本身。不过,我们预期大部分读者都熟悉Java,因此我们有时会拿Scala跟Java做对比,帮助这些读者理解它们之间的区别。
如何使用本书
由于本书的主旨是教学,我们推荐的阅读顺序是从前到后,依次阅读各章。我们尽可能每次只引入一个主题,同时只用已经介绍过的主题来解释这个新的主题。因此,如果跳过前面的章节,你也许会遇到某些概念并不十分理解。只要按顺序阅读,你会发现掌握Scala是循序渐进、顺理成章的。
如果你看到某个词汇不明白,记着查看词汇表和索引。许多读者都喜欢快速浏览特定的章节,这没有问题,词汇表和索引能帮助你随时找回阅读的坐标和方位。
当你读完本书以后,还可以继续用它来当作语言参考。Scala编程语言有一本正式的语言规范,但语言规范强调的是精确,而不是可读性。虽然本书不会覆盖Scala的每一个细节,它也足够全面,应该能够在你逐渐成为Scala编程能手的过程中,承担起语言参考书的职责。
如何学习Scala
通读本书,可以学到很多关于Scala的知识。不过,如果你做一些额外的尝试,可以学得更快,更彻底。
首先,可以利用好包含在本书中的代码示例。手动将这些示例录入,有助于在脑海中逐行过一遍代码。尤其是录入过程中尝试一些变化,会非常有趣,也能确信自己真的理解了它们背后的工作原理。
其次,时常访问在线论坛。这样,你和其他Scala爱好者可以互相促进。网上有大量的邮件列表、讨论组、聊天室、Wiki和Scala特定主题的订阅。花些时间,找到满足你需求的内容,你会在小问题上花更少的时间,有更多的精力投入到更深入、更重要的问题中。
最后,一旦你读得足够多,可以自己启动一个编程项目。从头编写小程序,或者为某个更大的项目开发组件。仅仅阅读并不会让你走得更远。
内容概览
第1章,“一门可伸缩的语言”,主要介绍Scala的设计及背后的概念和历史。
第2章,“Scala入门”,介绍了如何用Scala完成一些基础的编程任务,但并不深入讲解它们是如何工作的。本章的目的是让你可以开始键入Scala代码并执行。
第3章,“Scala入门(续)”,展示了更多基本的编程任务,帮助你快速上手Scala。学习完本章以后,你应该就能用Scala完成简单的脚本型任务了。
第4章,“类和对象”,开始深入介绍Scala,描述其基本的面向对象的组成部分,并指导大家如何编译并运行Scala应用程序。
第5章,“基本类型和操作”,介绍了Scala基本类型、字面量和支持的操作,(操作符的)优先级和结合性,以及对应的富包装类。
第6章,“函数式对象”,以函数式(即不可变)的分数(rational)为例,更深入地讲解Scala面向对象的特性。
第7章,“内建的控制结构”,展示了如何使用Scala内建的控制结构:if、while、for、try和match。
第8章,“函数和闭包”,给出了对函数的深入介绍,而函数是函数式编程语言最基本的组成部分。
第9章,“控制抽象”,展示了如何通过定义自己的控制抽象来对Scala基本的控制结构进行完善和补充。
第10章,“组合和继承”,更进一步探讨Scala对面向对象编程的支持。本章的主题不像第4章那么基础,但实践中经常会遇到。
第11章,“Scala的继承关系”,解释了Scala的继承关系,并探讨了通用方法和底类型等概念。
第12章,“特质”,介绍了Scala的混入(mixin)组合机制。本章展示了特质的工作原理,描述了特质的常见用法,并解释了特质相对于更传统的多重继承有哪些改进。
第13章,“包和引入”,讨论了大规模编程实践中我们会遇到的问题,包括顶级包、import语句,以及像protected和private那样的访问控制修饰符。
第14章,“断言和测试”,展示了Scala的断言机制,并介绍了用Scala编写测试的若干工具,特别是ScalaTest。
第15章,“样例类和模式匹配”,介绍了这组孪生的结构,让你更好地编写规则的、开放式的数据结构。样例类和模式匹配在处理树形的递归数据时非常有用。
第16章,“使用列表”,详细地解释了列表这个在Scala程序中使用最普遍的数据结构。
第17章,“使用其他集合类”,展示了如何使用基本的Scala集合,如列表、数组、元组、集和映射。
第18章,“可变对象”,解释了可变对象,以及Scala用来表示它们的语法。本章以一个具体的离散事件模拟案例分析收尾,展示了实践中可变对象的适用场景。
第19章,“类型参数化”,用具体的示例解释了第13章介绍过的信息隐藏的技巧:为纯函数式队列设计的类。本章接下来对类型参数的型变进行了说明,介绍了类型参数化对于信息隐藏的作用。
第20章,“抽象成员”,描述了Scala支持的各种抽象成员,不仅是方法可以被声明为抽象的,字段和类型也可以。
第21章,“隐式转换和隐式参数”,介绍了两个能够帮助你从源码中省去那些枯燥细节的概念,让编译器来自动填充或提供。
第22章,“实现列表”,描述了List类的实现。理解Scala列表的工作原理非常重要,List类的实现也展示了Scala若干特性的运用。
第23章,“重访for表达式”,展示了Scala如何将for表达式翻译成map、flatMap、filter和foreach。
第24章,“深入集合类”,详细介绍了Scala集合类库。
第25章,“Scala集合架构”,展示了集合类的构造,以及如何构建自制的集合。
第26章,“提取器”,展示了如何对任意的类进行模式匹配,而不是局限于使用样例类(做模式匹配)。
第27章,“注解”,展示了如何通过注解使用语言扩展。本章描述了若干标准的注解,并解释了如何构建自己的注解。
第28章,“使用XML”,解释了如何用Scala处理XML。本章展示了生成XML、解析XML和处理XML的常见用法。
第29章,“用对象实现模块化编程”,展示了如何使用Scala的对象构建模块化的系统。
第30章,“对象相等性”,指出了编写equals方法时需要考虑的若干问题和需要注意绕开的坑。
第31章,“结合Scala和Java”,探讨了在同一个工程中组合Scala和Java时会遇到的若干问题,并对如何解决这些问题给出了建议。
第32章,“Future和并发编程”,展示了如何使用Scala的Future类。尽管完全可以在Scala中使用Java平台的并发编程原语和类库,Scala的Future可以帮助你避开传统的“线程和锁”的并发编程模型里常见的死锁(deadlock)和争用状况(race condition)。
第33章,“组合子解析”,展示了如何用Scala的组合子(combinator)解析器(parser)类库构建解析器。
第34章,“GUI编程”,快速地介绍了可大幅简化基于Swing的GUI编程的Scala类库。
第35章,“SCells试算表”,通过展示一个完整的用Scala编写的试算表应用程序,将本书介绍的所有Scala特性组装串联起来。
“在这个示例中,greetStrings是一个类型为的值(”。。。
应为
“在这个示例中,greetStrings是一个类型为的Array[String]值(”。。。
Combinator Parse改为Combinator Parsing
第一章第二节(第七页)第二段第三行“而函数的类型是可被子类集成的类”中“集成”应为“继承”;
错误:整个
声明
周期都是有效的正确:整个
生命
周期都是有效的variable”
预发
应为
variable”
语法