《Clojure编程乐趣 第2版》PDF下载

  • 购买积分:14 如何计算积分?
  • 作  者:(美)福格斯(Michael Fogus),豪泽(Chris Houser )
  • 出 版 社:北京:人民邮电出版社
  • 出版年份:2017
  • ISBN:9787115443298
  • 页数:442 页
图书介绍:本书介绍的内容超出了语法,不只是如何编写Clojure代码;还将介绍函数式编程方法,并且将帮助读者掌握Lisp技术,以使得Clojure更为优雅和高效。本书侧重介绍如何以Clojure的方式思考问题。

第1部分 基础 3

第1章 Clojure哲学 3

1.1 Clojure之道 4

1.1.1 简单 4

1.1.2 专注 5

1.1.3 实用 5

1.1.4 清晰 6

1.1.5 一致 7

1.2 为何(又一种)Lisp 8

1.2.1 优美 8

1.2.2 极度灵活 9

1.3 函数式编程 15

1.3.1 一个可行的函教式编程定义 15

1.3.2 函数式编程的内涵 16

1.4 Clojure为何不是面向对象的 16

1.4.1 定义术语 16

1.4.2 命令式“烘烤” 18

1.4.3 OOP提供的大多数东西,Clojure也有 18

1.5 小结 23

第2章 Clojure疾风式教程 24

2.1 基本数据类型 25

2.1.1 数字 25

2.1.2 整数 25

2.1.3 浮点数 26

2.1.4 有理数 26

2.1.5 符号 27

2.1.6 关键字 27

2.1.7 字符串 27

2.1.8 字符 28

2.2 组合起来:集合 28

2.2.1 list 28

2.2.2 vector 29

2.2.3 map 29

2.2.4 set 29

2.3 付诸实现:函数 29

2.4 var 30

2.5 函数 30

2.5.1 匿名函数 31

2.5.2 使用def和defn定义命名函数 31

2.5.3 不同参数数量的函数 32

2.5.4 以#()定义原位(in-place)函数 33

2.6 局部量、循环和block 33

2.6.1 block 34

2.6.2 局部量 34

2.6.3 循环 35

2.7 防止发生:quote 37

2.7.1 求值 37

2.7.2 Quoting 38

2.7.3 反quote 40

2.7.4 反quote拼接 41

2.7.5 auto-gensym 41

2.8 与Java互操作 41

2.8.1 访问静态类成员(仅限于Clojure) 41

2.8.2 创建Java实例 42

2.8.3 用.运算符访问Java实例成员 42

2.8.4 设置Java实例属性 43

2.8.5 ..宏 43

2.8.6 doto宏 44

2.8.7 定义类 44

2.9 异常环境 44

2.10 命名空间 45

2.10.1 用ns创建命名空间 45

2.10.2 用:require加载其他命名空间 46

2.10.3 用:refer加载和创建映射 47

2.10.4 用:refer创建映射 47

2.10.5 用:import加载Java类 48

2.11 小结 48

第3章 小试牛刀 49

3.1 真值 50

3.1.1 什么是真 50

3.1.2 不要创建布尔对象 50

3.1.3 nil vs.false 51

3.2 小心翼翼nil双关 51

3.3 解构 53

3.3.1 你的任务,你应该选择接受 53

3.3.2 解构vector 53

3.3.3 解构map 55

3.3.4 解构函数参数 57

3.3.5 解构vs.访问器方法 57

3.4 用REPL做试验 57

3.4.1 试验seq 57

3.4.2 试验图形化 59

3.4.3 知识汇总 60

3.4.4 出错之时 61

3.4.5 只为乐趣 62

3.5 小结 63

第2部分 数据类型 67

第4章 标量 67

4.1 理解精度 68

4.1.1 截断(Truncation) 68

4.1.2 提升(Promotion) 69

4.1.3 上溢(Overflow) 69

4.1.4 下溢(Underflow) 70

4.1.5 舍入错误(Rounding errors) 70

4.2 有理数 71

4.2.1 为什么是有理数 71

4.2.2 怎样才是有理数 72

4.2.3 有理数的合理性 73

4.3 使用关键字的时机 73

4.3.1 关键字的应用 73

4.3.2 限定关键字 75

4.4 符号解析 76

4.4.1 元数据 77

4.4.2 符号与命名空间 78

4.4.3 Lisp-1 78

4.5 正则表达式——第二个问题 79

4.5.1 语法 79

4.5.2 函数 80

4.5.3 小心可变匹配器(matcher) 81

4.6 小结 81

第5章 组合数据类型 82

5.1 持久化、序列和复杂度 83

5.1.1 “你一直用着这个词。我认为,这并不意味着它就是你以为的含义” 83

5.1.2 序列术语及其含义 84

5.1.3 大O 87

5.2 vector:创建和使用其各种变体 89

5.2.1 构建vector 89

5.2.2 大vector 90

5.2.3 vector当作栈 93

5.2.4 使用vector而非reverse 94

5.2.5 子vector 95

5.2.6 vector当作MapEntry 95

5.2.7 vector不是什么 96

5.3 list:Clojure代码form的数据结构 97

5.3.1 像Lisp那样的list 97

5.3.2 list当作栈 98

5.3.3 list不是什么 98

5.4 如何使用持久化队列 99

5.4.1 什么都没有的队列 99

5.4.2 入队 100

5.4.3 获取 101

5.4.4 出队 101

5.5 持久化set 101

5.5.1 Clojure set的基本属性 101

5.5.2 用sorted-set保持set的顺序 103

5.5.3 contains? 103

5.5.4 clojure.set 104

5.6 思考map 106

5.6.1 hash map 106

5.6.2 以有序map保持键值的顺序 107

5.6.3 用数组map保持插入顺序 108

5.7 知识汇总:在序列里查找某项的位置 109

5.8 小结 111

第3部分 函数式编程 115

第6章 惰性与不变性 115

6.1 关于不变性:按照自己的方式去使用 115

6.1.1 什么是不变性 116

6.1.2 不变性可以做什么 116

6.2 设计一个持久化玩具 118

6.3 惰性 121

6.3.1 以“逻辑与”熟悉惰性 122

6.3.2 理解lazy-seq的秘诀 123

6.3.3 丢掉头 126

6.3.4 采用无限序列 126

6.3.5 delay和force宏 128

6.4 知识汇总:一个惰性的快速排序程序 130

6.5 小结 133

第7章 函数式编程 134

7.1 各种形式的函数 134

7.1.1 一等函数 135

7.1.2 高阶函数 138

7.1.3 纯函数 141

7.1.4 命名实参 143

7.1.5 使用前置条件和后置条件约束函数 143

7.2 闭包 145

7.2.1 函数返回闭包 146

7.2.2 隐藏参数 147

7.2.3 将闭包当作函数传递 148

7.3 递归思考 152

7.3.1 普通递归 152

7.3.2 尾递归和recur 155

7.3.3 勿忘trampoline 157

7.3.4 延续传递风格 159

7.4 知识汇总:A*寻路 161

7.4.1 世界 161

7.4.2 近邻 161

7.4.3 A*实现 163

7.4.4 A*实现的笔记 165

7.5 小结 166

第4部分 大规模设计 169

第8章 宏 169

8.1 数据即代码即数据 170

8.1.1 语法quote、反quote和拼接 171

8.1.2 宏之经验谈 173

8.2 定义控制结构 173

8.2.1 不用语法quote定义控制结构 174

8.2.2 使用语法quote和反quote定义控制结构 175

8.3 组合form的宏 176

8.4 使用宏改变form 177

8.5 使用宏控制符号解析时间 181

8.5.1 回指 181

8.5.2 (可能)有用的选择性名字捕获 182

8.6 使用宏管理资源 183

8.7 知识汇总:返回函数的宏 184

8.8 小结 187

第9章 组合数据与代码 188

9.1 命名空间 188

9.1.1 创建命名空间 189

9.1.2 只暴露所需 191

9.1.3 声明性包含和排除 194

9.2 以通用设计模式探索Clojure多重方法 194

9.2.1 组成部分 195

9.2.2 用法 196

9.2.3 以多重方法拯救 197

9.2.4 处理继承行为的特别继承 197

9.2.5 解析层次中的冲突 198

9.2.6 真正的最大功率任意分发 199

9.3 类型、协议和记录 200

9.3.1 记录 200

9.3.2 协议 203

9.3.3 用deftype从更原始的基础开始构建 211

9.4 知识汇总:国际象棋移动的流畅构建器 213

9.4.1 Java实现 213

9.4.2 Clojure实现 215

9.5 小结 217

第10章 变化和并发 218

10.1 使用Ref的时机 219

10.1.1 利用ref构建可变棋盘 221

10.1.2 事务 223

10.1.3 嵌入式事务 225

10.1.4 STM使其简单的事情 225

10.1.5 潜在缺陷 226

10.1.6 让STM不高兴的事 227

10.2 利用refs重构 228

10.2.1 解决棋盘例子 228

10.2.2 以commute进行可交换的改变 230

10.2.3 以ref-set进行普通改变 231

10.2.4 压力之下的Ref 232

10.3 使用Agent的时机 233

10.3.1 进程内并发模型vs分布式并发模型 234

10.3.2 用Agent控制I/O 235

10.3.3 send和send-off之间的差异 237

10.3.4 错误处理 239

10.3.5 何时不用Agent 241

10.4 使用Atom的时机 241

10.4.1 跨线程共享 242

10.4.2 在事务里使用Atom 242

10.5 使用lock的时机 244

10.5.1 使用锁进行安全变化 245

10.5.2 使用Java的显式锁 246

10.6 var和动态绑定 248

10.6.1 binding宏 248

10.6.2 创建命名var 250

10.6.3 创建匿名var 251

10.6.4 动态作用域 251

10.7 小结 253

第11章 并行 254

11.1 使用future的时机 255

11.2 使用promise的时机 259

11.2.1 以promise进行并行任务 260

11.2.2 回调API到阻塞API 261

11.2.3 确定性死锁 262

11.3 并行 263

11.3.1 pvalues 263

11.3.2 pmap 263

11.3.3 pcalls 264

11.4 reduce/fold 264

11.5 小结 265

第5部分 宿主共生关系 269

第12章 Java.next 269

12.1 使用proxy动态生成对象 270

12.2 Clojure gen-class和GUI程序设计 277

12.2.1 命名空间作为类的规范 277

12.2.2 命名空间编译内幕 280

12.2.3 以Clojure探索用户界面设计与开发 281

12.3 Clojure同Java数组的关系 284

12.3.1 数组的类型:原生与引用 284

12.3.2 数组可变性 286

12.3.3 那个不幸的命名约定 286

12.3.4 多维数组 287

12.3.5 调用可变方法/构造函数 288

12.4 所有Clojure函数都实现…… 288

12.4.1 java.util.Comparator 288

12.4.2 java.lang.Runnable 289

12.4.3 java.util.concurrent.Callable 290

12.5 在Java API里使用Clojure数据结构 290

12.5.1 java.util.List 291

12.5.2 java.lang.Comparable 291

12.5.3 java.util.RandomAccess 292

12.5.4 java.util.Collection 292

12.5.5 java.util.Set 293

12.6 definterface 293

12.7 慎用异常 295

12.7.1 一点异常的背景 296

12.7.2 运行时异常vs.编译时异常 296

12.7.3 处理异常 298

12.7.4 定制异常 299

12.8 小结 300

第13章 ClojureScript 301

13.1 实现VS接口 302

13.2 编译器内部:分析和发布 305

13.2.1 编译步骤 305

13.2.2 Web Audio 307

13.2.3 高级编译 311

13.2.4 生成extern.js文件 313

13.3 编译和运行 315

13.4 小结 319

第6部分 杂项考量 323

第14章 面向数据编程 323

14.1 代码是代码,数据是数据 323

14.1.1 严格的分界 324

14.1.2 ORMG 325

14.1.3 从数据中获取信息的一般方式 326

14.1.4 PLOP 327

14.2 数据就是数据 327

14.2.1 值的好处 328

14.2.2 标签符号 332

14.3 数据就是代码 335

14.3.1 数据可编程引擎 335

14.3.2 可编程数据引擎的例子 336

14.3.3 例子:简单的事件来源 337

14.4 代码就是数据,也是代码 345

14.4.1 哈特的发现和同像性 346

14.4.2 Clojure代码就是数据 346

14.4.3 规范括号 346

14.5 小结 349

第15章 性能 351

15.1 类型提示 352

15.1.1 类型修饰的优势 352

15.1.2 类型提示实参和返回值 352

15.1.3 类型提示对象 354

15.2 暂态(transient) 354

15.2.1 短暂的垃圾 354

15.2.2 暂态在效率上与可变集合相比较 355

15.3 分块序列 356

15.4 记忆 358

15.4.1 记忆再研究 359

15.4.2 记忆协议 359

15.4.3 面向抽象编程 361

15.5 理解强制转型(coercion) 361

15.5.1 使用原始类型long 362

15.5.2 使用原生double 364

15.5.3 使用自动提升精度 365

15.6 可缩小的 366

15.6.1 简单的精简集合的例子 366

15.6.2 派生第一个reducse函数变种 367

15.6.3 更多的可还原函数的转换器 369

15.6.4 reducible转换器 371

15.6.5 reducible的性能 372

15.6.6 reducible的缺陷 373

15.6.7 整合reducible到Clojure reduce 373

15.6.8 fold函数:并行的reduce 375

15.7 小结 377

第16章 思考程序 378

16.1 搜索问题 378

16.2 统一思考数据 383

16.2.1 潜在的平等性或满足性 384

16.2.2 替换 387

16.2.3 一致性 388

16.3 关于core.logic 390

16.3.1 都是关于一致性 390

16.3.2 关系型 391

16.3.3 子目标 394

16.4 约束 397

16.4.1 约束编程介绍 397

16.4.2 通过有限域限制绑定 399

16.4.3 利用有限域解决数独问题 400

16.5 小结 403

第17章 Clojure改变我们的思考方式 405

17.1 DSL 406

17.1.1 无所不在的DSL 406

17.1.2 实现类似SQL的DSL用于生成查询 408

17.1.3 Clojure方式DSL的注记 413

17.2 测试 413

17.2.1 一些有用的技术 414

17.2.2 契约式程序设计 416

17.3 缺乏设计模式 417

17.4 错误处理和调试 426

17.4.1 错误处理 426

17.4.2 调试 429

17.5 珍重 433

附录 资源 434

Miscellaneous resources 434

Online resources 440