首页>参考读物>计算机科学与技术>软件与程序设计

Clojure编程实战(原书第2版)
作者 : [美] 阿米特·拉索尔(Amit Rathore) 弗朗西斯·阿维拉(Francis Avila) 著
译者 : 姚军 等译
丛书名 : 华章程序员书库
出版日期 : 2018-09-29
ISBN : 978-7-111-60938-4
定价 : 79.00元
扩展资源下载
扩展信息
语种 : 简体中文
页数 : 293
开本 : 16
原书名 : Clojure in Action,Second Edition
原出版社: Waterside Productions,Inc.
属性分类: 店面
包含CD : 无CD
绝版 : 未绝版
图书简介

本书是一本优秀的Clojure入门指南。书中从抽象的理论到实际的案例,对Clojure语言进行了全面、系统的阐释,可以帮助你快速掌握编写大规模Clojure程序所必需的特性、概念和技术。
本书共11章,第1章概要介绍Clojure语言及其三大支柱;第2章介绍REPL(读取-求值-打印循环,这是Clojure的命令行解释程序),帮助你开始编写Clojure代码;第3章介绍Clojure更独特的功能,包括元数据、异常处理、高阶函数、两组作用域规则(词法和动态)、组织代码的命名空间等;第4章讨论三种基本的多态性和使用多重方法时各种多态性在Clojure中的表现;第5章介绍Clojure与JVM的结合;第6章解释Clojure的状态管理和并行方法,以及四种基本的并行原语;第7章介绍Clojure的宏系统;第8章深入介绍函数式编程范式,以及高阶函数的利用方法;第9章处理表达问题;第10章说明如何将编写测试驱动代码的过程与Clojure REPL相结合,显著提升效率;第11章介绍高级宏和DSL。

图书特色

0

上架指导

计算机\程序设计

封底文字

Clojure是用于JVM的一种现代化Lisp语言,具有你所期待的优势:第一类函数、宏、清晰的Lisp编程风格。它支持函数式编程,对并发编程和创建领域特定语言来说非常理想。Clojure可以解决更困难的问题,做出更快的更改,最终得到更小的代码库。因此,Clojure有许多成功案例是毫不奇怪的。
本书第2版做了大量修订和更新,涵盖Clojure 1.6的新特性。本书从抽象的理论到实际的案例,对Clojure语言进行了全面、系统的阐释。首先,你将了解Clojure作为通用语言的使用方法。接着,你将探索Clojure高效的并发模型,这种模型基于软件事务内存(STM)的数据库概念。通过在JVM上运行的Clojure DSL,效率将提高到一个新的水平。在阅读本书的过程中,你还将学习关于编写更小、更安全、更快速代码的无数技巧和技术。

本书内容:
函数式编程基础知识 使用Clojure宏进行元编程
Java互操作 Clojure 1.6介绍

Palak Mathur,Capital One
一本写给所有技术水平程序员的优秀图书。
Jeff Smith,Single Source Systems
全面解释了函数式编程,是Clojure优秀入门书籍之一。
Scott M. Gardner,Multimedia LLC
很好地平衡了Cojure惯用手法以及如何在更大的Java生态系统务实地使用它。
Jonathan Rioux,RGA Canada
提供了一个快速理解Clojure的实用途径!

图书序言

第2版序言 Preface to the second edition
许多新接触Clojure的人都来自企业软件领域,包括本书的主要作者阿米特·拉索尔。在他们的世界里,刻板的静态类型、面向对象语言与由工具、框架和程序库组成的庞大生态系统联系在一起,这些工具、框架和程序库的设计主旨是降低组件和不断变化的业务需求之间的耦合度。这是包含依赖注入、Servlet容器、XML配置和代码生成的Java及C#世界。因为Clojure运行于Java之上,所以它成为试图摆脱这一领域复杂性同时又不想完全放弃熟悉且优秀工具的人的不二之选。对于Clojure,企业软件开发人员害怕和不熟悉的特性是动态类型和一阶函数,但是Clojure吸引人的地方在于摆脱附带复杂性和静态类型,同时仍然可以在必要时使用旧代码。
我来自Web开发的“狂野西部”,那是PHP、JavaScript、Python和Ruby等动态类型编程语言的疯狂世界。这些语言中,有些在最初设计时很少(甚至没有)考虑过在大项目上的实用性,并且为了适应大项目而匆忙地发展出了新功能和变通方法。许多使用者(包括我)都没有经过计算机科学训练,职业生涯可能始于摆弄HTML,为日常工作提供一个网站。他们的编程知识和所使用的语言一样,都是随着网站的成长而匆忙获得的。和企业软件领域不同,动态类型、自动类型强制和后期绑定是常规做法,第一类函数很常见,面向对象也不是基本前提。在这个领域里仍然有由框架和程序库组成的大型生态系统,但是它们不像企业软件开发中那样遵守规范和面向配置。对于Web开发人员来说,Clojure最可怕的是其背后潜伏的企业软件“幽灵”—(简言之)Java。对于企业开发人员来说,Clojure的Java传承是一个特性,而这对于Web开发人员则是一个bug。
如果你来自Web开发者的世界,那么我可以告诉你:不用害怕Java。许多企业软件的复杂性是体现在编译时的:静态类型、冗长的代码和许多XML配置。在流行的Web开发语言中,复杂性体现在运行时:弱类型和极端的动态性及易变性使程序难以推导。我正是在寻找这种附带复杂性的更好解决方案时发现了Clojure,我对Java也持怀疑态度。我听说过Java EE的各种传说,看到过庞大的类文件和工厂接口。我感到疑惑:Clojure是在Java这种死板、脆弱和复杂的软件栈基础上构建的,那么它怎么能够更好地控制软件复杂性?该如何平衡所有括号?
Clojure处于混乱的Web开发领域和过于规格化的企业软件领域之间,前者的代码库难以安全地更改,后者的代码库则冗长且难以理解。Clojure在我的程序上施加的限制比编写PHP时更严格,但是这种纪律性没有任何负面影响:你的代码仍然和往常一样简洁(也许还更简洁);你可以轻松且毫无痛苦地利用Java生态系统的许多优势,例如健全的包管理和基于JAR的部署;由于JVM,你的应用程序还可能运行得更快!
甚至在我成为专业的Clojure编码者之前,它就已经给我带来了好处。深入理解Clojure的简洁性和不可变性哲学,帮助我认识到在其他语言编程中遭遇的复杂性的根源,从而更好地控制复杂性。我现在以编写Clojure(和ClojureScript)为生,诚然,我的软件中仍然有许多附带复杂性,但是发现和控制它们变得更轻松了,我所编写的软件是使用PHP或者Python时做梦也想不到的。
本书的第1版帮助我走上Clojure的道路,那正是我现在的道路。我很荣幸能参与第2版的写作,希望它也能够帮助你“驯服”软件复杂性。不要害怕Java或者括号!它们实际上都相当“驯良”。

弗朗西斯·阿维拉





第1版序言 Preface to the first edition
我可以告诉你,我有多享受极客的生活;我可以告诉你,1985年父亲给我展示穿孔卡时,我有多么着迷;我可以告诉你,我在7岁时是如何得到第一台计算机的;我还可以告诉你,我从1989年起就爱上了编程。我可以告诉你关于这一切的许多事情,但是不能肯定它们是否有趣。
作为替代,还是让我告诉你们我对答案的追求吧。多年以来,关于我们所在行业的一些问题一直困扰着我:为什么从来没有一个软件项目像它应有的那样简单?为什么没有一个项目能够按照时间和预算完成?为什么程序中总是有bug?为什么软件从来不按照人们的意图工作?为什么对软件进行更改总是那么困难?为什么不管一个项目开始时有多么清晰的计划,却总会变成一个“大泥球”?
几乎每个人都会认识到这些问题,但他们似乎接受这种现状。行业中的大部分人通过在时间安排和预算上设置缓冲以及接受普通水平的软件来应对它们。难道没有更好的办法了吗?
本书不是答案,绝对不是,但它是我向前探索的一部分。我的想法是,工具越好,越能够帮助我们创建好的软件。
这就引出了显而易见的问题:什么是更好的工具?它们在哪方面表现更好?我的答案便是,好的工具是能够更好地帮助控制复杂性的工具。毕竟,复杂性是我们所在世界中一切状态的根源。确实,Fred Brooks早在1986年就在一篇文章中提到了复杂性。他提出了基本复杂性和附带复杂性之间的区别。基本复杂性是问题领域中固有的,而附带复杂性是由问题领域之外的事物引入的。例如,在处理纳税申报的软件项目中,由复杂的纳税编码引入的复杂性是问题领域的一部分,因此其是基本复杂性。而由错综复杂的访问模式引起的任何复杂性则是附带复杂性。
那么,让我来改变一下措辞:好的工具能帮助我们减少附带复杂性。这些工具让我们尽可能好地完成工作,而且不会成为前进道路上的障碍。另外,出色的工具更不止于此,会为我们提供各种手段,提高设计人员和编程人员的效率,并且自身不会引入问题。Lisp编程语言就是为了成为这样的工具而被设计的。Clojure则是设计极其精巧的Lisp。
每个遇上Lisp的程序员都有自己的故事,我的故事和许多人类似。我的职业生涯从Java开始,最终撞上了一堵自己建立的墙。于是我开始探索动态语言,它们看起来更有表现力和可塑性。我喜欢使用Python和Ruby,并用它们编写了多个重要应用。当时我在一家名为ThoughtWorks的公司工作,有许多志同道合的同事。最终,其中一个人带领我转向Common Lisp。对这种语言的理解越深,我就越强烈地意识到其他语言的粗糙。我在几个个人项目上使用了Common Lisp,但是从未将其应用于重大项目。不过,它对我使用其他所有语言的编码工作都产生了深远的影响,我不断地寻找机会,试图将Lisp应用于现实世界的项目中。
我在2008年终于得到了机会。那时,我搬到加州湾区,加入了一家初创企业Runa的创建团队。按照真正的硅谷传统,我们的第一个办公室在创始人的车库里。我们希望凭借Runa公司的力量搅乱电子商务领域,想法是收集大量数据,用机器学习技术完全领会它们,然后提出个性化的交易,实时选择购物者。为了完成这些工作,我们必须攻克真正的技术难关。该系统必须每秒处理数千个请求,每天处理数太字节(TB)的数据;它还必须能够通过一组高级的陈述性领域特定语言(DSL)来编写脚本;它必须支持代码热交换,以便在运行中更新;它必须运行于云上,还必须完全由API驱动。我们不得不在缺乏资源的情况下完成该系统,因为设计团队只有三个人。
由于这些约束,我们需要一种能够提供“杠杆”的语言。因此,我们转向名为Clojure的新语言。这是一种运行于JVM之上的现代化函数式语言,它还承诺解决并发多线程代码中固有的问题。而且,它还是Lisp语言的一个变种!
我曾是这家初创企业的架构师,现在是工程副总裁。我将未来的成功押在这个名不见经传的人创建的新型编程语言(当时还在预发行阶段)上。但是我所读到的有关它的一切都与我产生了共鸣—一切都是那么合适。从那时起,我们使用Clojure取得了难以置信的成功。我们的团队在过去三年中成长了起来,但是仍然比类似公司的其他团队小一个数量级。我怀疑那些团队使用的是旧的Java。过去的经验让我坚定了信念,在其他条件相同的情况下,工具非常重要,而有些工具远优于其他工具。
当我们开始着手工作时,我曾将Clojure当成秘密武器—但是Clojure的社区很强大,并且是相互扶持的,因此将其作为一个公开的秘密似乎是更好的想法。我启动了湾区的Clojure用户组,现在已经有数百名成员。已经有几十个人来参加过我们的会议,喜欢在会上听到的内容,并决定在自己的项目上使用Clojure。
出于相同的信念,我编写了这本书,分享使用Clojure的经验,希望可以说服你们中的一些人,不仅看到这些“括号”,还能了解Lisp语言的总体能力和Clojure的具体特性。希望你们能觉得这本书实用且有趣。

阿米特·拉索尔

作者简介

[美] 阿米特·拉索尔(Amit Rathore) 弗朗西斯·阿维拉(Francis Avila) 著:阿米特·拉索尔(Amit Rathore)有12年构建大规模、数据密集型应用的开发经验,目前正在为一个高分布式、高负载、实时的大数据系统开发Clojure代码。


弗朗西斯·阿维拉(Francis Avila) Breeze的软件开发工程师,有7年Web前端和后端开发经验。

译者序

自编程语言出现以来,更好地管理复杂的抽象、清晰且简短的代码以及编程语言本身的可扩展性一直是无数程序员追求的目标,这催生了以静态类型、面向对象编程方法为基础的Java等企业级编程语言,以及以快速Web开发为目的的JavaScript、Ruby、Python等动态类型脚本语言。
但不管是上述的哪一种语言,在新的问题领域不断出现之时,它们都带来了越来越多的附带复杂性,那么如何控制这种复杂性,同时利用历史遗留下来的巨大生态系统及已有代码呢?Clojure就是这样的利器。它具备Lisp类语言的函数式编程风格,通过高阶函数、不可变数据对象等特性,生成更加清晰、一致且易于理解的代码,而且极好地解决了多线程条件下的编程难题,达到了其他语言难以企及的并发程度。Clojure语言核心短小紧凑、语法简单明了,许多功能是通过其强大的宏系统实现的,这又使它具备了自扩展能力,可以轻松地增加语言特性甚至为非编程人员提供强大的领域特定语言。最难得的是,Clojure植根于JVM,并且提供了丰富的Java互操作功能,不仅可以轻松地共享Java语言长年积累下来的强大程序库和生态系统,利用原有代码,还可以让Java开发团队享受到新型语言的便利,可谓“鱼与熊掌兼得”。
本书的两位作者来自不同的开发领域,他们将企业编程和Web应用开发的知识熔于一炉,用既贴近现实应用又便于理解的实例,阐述了编程语言中这一后起之秀的方方面面。在不知不觉之中,读者可以体会到函数式编程的威力,熟悉原本令人望而生畏的独特语法,最终沉浸于新技术带来的快乐之中。详尽的解说、丰富的实例,也使本书成为Clojure语言的必备入门书籍。
本书的翻译工作主要由姚军完成,徐锋、刘建林、陈志勇、宁懿、白龙、陈美娜、谢志雄、方翊、林耀成、陈霞等人也为翻译工作做出了贡献,在此衷心感谢机械工业出版社华章分社的编辑王春华老师和其他有关人员为本书所提的宝贵意见。

姚军
2018年7月

图书目录

译者序
第1版赞誉
第2版序言
第1版序言
关于本书
致谢
第1章 Clojure简介1
1.1 Clojure的概念以及采用的原因1
1.1.1 Clojure:现代化的Lisp语言2
1.1.2 Clojure:务实的函数式编程3
1.1.3 JVM之上的Clojure5
1.2 语言基础知识6
1.2.1 Lisp语法6
1.2.2 括号8
1.3 宿主互操作性:JVM速成教程9
1.3.1 Java类型、类和对象10
1.3.2 点(.)和new运算符11
1.3.3 线程和并发性12
1.4 小结12
第2章 Clojure要素:数据结构和函数14
2.1 在REPL上编码14
2.1.1 Clojure REPL15
2.1.2 “Hello, world!”16
2.1.3 用doc、find-doc和apropos查找文档17
2.1.4 Clojure语法的另外几个要点19
2.2 Clojure数据结构21
2.2.1 nil、真值和假值21
2.2.2 字符和字符串22
2.2.3 Clojure数值22
2.2.4 符号和关键字23
2.2.5 列表25
2.2.6 向量26
2.2.7 映射28
2.2.8 序列30
2.3 程序结构31
2.3.1 函数31
2.3.2 let形式32
2.3.3 do的副作用33
2.3.4 读取器宏34
2.4 程序流程35
2.4.1 条件35
2.4.2 逻辑函数37
2.4.3 函数式循环40
2.4.4 串行宏45
2.5 小结49
第3章 Clojure构件50
3.1 元数据51
3.1.1 Java类型提示53
3.1.2 Java原始类型和数组类型54
3.2 Java异常:try和throw55
3.3 函数56
3.3.1 定义函数57
3.3.2 调用函数63
3.3.3 高阶函数64
3.3.4 编写高阶函数67
3.3.5 匿名函数69
3.3.6 关键字和符号70
3.4 作用域73
3.4.1 变量和绑定73
3.4.2 重温let形式78
3.4.3 词法闭包79
3.5 命名空间79
3.5.1 ns宏80
3.5.2 使用命名空间82
3.6 解构83
3.6.1 向量绑定84
3.6.2 映射绑定85
3.7 读取器字面量87
3.8 小结89
第4章 多重方法多态90
4.1 多态及其类型90
4.1.1 参数化多态91
4.1.2 随意多态91
4.1.3 子类多态93
4.2 用多重方法实现多态94
4.2.1 不使用多重方法时的情况94
4.2.2 使用多重方法实现随意多态95
4.2.3 多分派98
4.2.4 使用多重方法实现子类多态99
4.3 小结105
第5章 探索Clojure和Java互操作106
5.1 从Clojure中调用Java107
5.1.1 将Java类导入Clojure107
5.1.2 创建实例108
5.1.3 访问方法和域108
5.1.4 宏和句点特殊形式109
5.1.5 有助于使用Java的Clojure宏112
5.1.6 实现接口和扩展类114
5.2 将Clojure代码编译为Java字节码115
5.2.1 示例:两个计算器的故事116
5.2.2 用gen-class和gen-interface创建Java类和接口118
5.3 从Java调用Clojure122
5.4 小结123
第6章 状态和并发的世界124
6.1 状态存在的问题125
6.1.1 共享状态的常见问题125
6.1.2 传统解决方案125
6.2 标识与值的分离127
6.2.1 不可变值128
6.2.2 对象和时间129
6.2.3 不可变性和并发性130
6.3 Clojure的方法130
6.3.1 不可变性与性能131
6.3.2 托管引用132
6.4 引用132
6.4.1 创建引用132
6.4.2 引用突变133
6.4.3 软件事务内存135
6.5 代理137
6.5.1 创建代理137
6.5.2 代理突变137
6.5.3 使用代理139
6.5.4 STM事务中的副作用141
6.6 原子141
6.6.1 创建原子142
6.6.2 原子突变142
6.7 变量143
6.7.1 创建变量和根绑定143
6.7.2 变量绑定144
6.8 状态及其统一访问模型145
6.8.1 创建145
6.8.2 读取145
6.8.3 突变145
6.8.4 事务146
6.8.5 监视突变146
6.9 决定使用哪种托管引用类别147
6.10 future和promise148
6.10.1 future148
6.10.2 promise149
6.11 小结150
第7章 通过宏发展Clojure151
7.1 宏的基础知识152
7.1.1 文本替换152
7.1.2 unless示例153
7.1.3 宏模板156
7.1.4 回顾:为什么使用宏160
7.2 Clojure内部的宏161
7.2.1 comment161
7.2.2 declare161
7.2.3 defonce162
7.2.4 and162
7.2.5 time163
7.3 编写自己的宏163
7.3.1 infix164
7.3.2 randomly164
7.3.3 defwebmethod165
7.3.4 defnn166
7.3.5 assert-true167
7.4 小结169
第8章 函数式编程深入研究170
8.1 使用高阶函数170
8.1.1 收集函数结果171
8.1.2 对一系列事物进行归纳173
8.1.3 过滤一系列事物174
8.2 部分应用175
8.2.1 函数适配176
8.2.2 定义函数179
8.3 闭包180
8.3.1 自由变量与闭包180
8.3.2 延迟计算与闭包181
8.3.3 闭包与对象182
8.3.4 一个Clojure对象系统184
8.4 小结196
第9章 协议、记录和类型197
9.1 表达式问题197
9.1.1 建立示例场景198
9.1.2 对表达式问题的仔细观察和一些潜在的解决方案201
9.1.3 Clojure多重方法解决方案202
9.2 研究表达式问题的运算端204
9.2.1 def-modus-operandi204
9.2.2 detail-modus-operandi205
9.2.3 跟踪你的操作方法205
9.2.4 解决方案的错误处理和故障点211
9.3 用协议研究表达式问题的数据类型方面211
9.3.1 defprotocol与extend-protocol212
9.3.2 用defrecord、deftype和reify定义数据类型217
9.4 小结222
第10章 测试驱动开发及其他223
10.1 TDD入门:操纵字符串中的日期223
10.1.1 第一个断言224
10.1.2 month-from和year-from226
10.1.3 as-string227
10.1.4 递增和递减228
10.1.5 无情地重构230
10.2 通过模拟和打桩改善测试231
10.2.1 示例:费用查找器231
10.2.2 打桩232
10.2.3 模拟234
10.2.4 模拟与桩的对比235
10.2.5 管理打桩和模拟状态238
10.3 组织测试239
10.3.1 testing宏240
10.3.2 are宏240
10.4 小结241
第11章 更多的宏和DSL242
11.1 对宏的快速回顾242
11.2 指代宏244
11.2.1 指代式if244
11.2.2 thread-it宏246
11.3 将计算转移到编译时249
11.3.1 示例:不使用宏的循环加密249
11.3.2 让编译器更努力地工作252
11.4 生成宏的宏254
11.4.1 示例模板254
11.4.2 实现make-synonym255
11.4.3 使用宏生成宏的原因258
11.5 领域特定语言258
11.5.1 DSL驱动设计258
11.5.2 用户分类260
11.6 小结270
附录A 安装Clojure271
结  语275

教学资源推荐
作者: (美)Richard Johnsonbaugh, Martin Kalin
作者: (美)布莱恩·R. 霍尔(Brian R.Hall) 凯文·J.斯隆卡(Kevin J.Slonka)著
作者: 郑阿奇,梁敬东
参考读物推荐
作者: 解承凯 编著
作者: (美)Jennifer Campbell; Paul Gries; Jason Montojo; Greg Wilson 著
作者: 钟志勇 何威俊 冯煜博 著