第1章进入Clojure仙境 1
为什么要选择Clojure? 1
获取Clojure 3
Clojure REPL 3
不!括号真的不会让你瞎了眼 6
表达式、操作符、语法以及优先级 7
同像性 10
Clojure Reader 12
标量字面量 13
注释 18
空格和逗号 19
集合字面量 20
reader的一些其他语法糖 20
命名空间 21
符号求值 23
特殊形式 24
阻止求值:quote 25
代码块:do 26
定义Var:def 27
本地绑定:let 27
解构(let,第2部分) 29
定义函数:fn 36
条件判断:if 42
循环:loop和recur 43
引用var : var 44
和Java的互操作:和new 45
异常处理:try和throw 45
状态修改:set! 46
锁的原语:monitor-enter和monitor-exit 46
小结 46
eval 47
这只是开始 48
第1部分 函数式编程以及并发 51
第2章 函数式编程 51
所谓函数式编程,到底意味着什么? 52
谈谈值的重要性 52
关于值 53
值与可变对象的比较 54
一个关键性的选择 58
作为头等公民的函数以及高阶函数 59
Apply, Partial 64
函数(功能)的组合 68
编写高阶函数 71
利用可组合的高阶函数构建一个日志系统 72
纯函数 76
为什么纯函数很有意思? 77
现实生活中的函数式编程 79
第3章集合类与数据结构 81
抽象优于实现 82
集合:collection 85
序列:Sequence 87
Associative 97
索引集合:Indexed 101
栈:stack 103
set 103
有序集合:sorted 104
访问集合元素的简洁方式 109
习惯用法 111
集合、key以及高阶函数 111
数据结构的类型 113
列表:List 113
vector 114
set 115
map 116
不可变性和持久性 121
持久性与结构共享 122
易变集合 128
元数据 133
用Clojure的集合来小试牛刀 135
标识符和循环引用 135
思维方式的改变:从命令式到函数式 137
遍历、更新以及Zipper 151
总结 157
第4章多线程和并发 159
计算在时间和空间内的转换 160
delay 160
future 162
promise 163
简单的并行化 166
状态和标识 168
Clojure的引用类型 170
并发操作的分类 172
原子类型(Atom) 174
通知和约束 176
观察器 177
校验器 179
ref 180
软件事务内存 180
对ref进行修改的机制 181
STM的一些缺点 192
var 198
定义var 199
动态作用域 202
var不是变量 207
前置声明 208
agent 209
处理agent action中的错误 212
1/O、事务以及嵌套的Send 215
使用Java的并发原语 225
Locking 226
总结 226
第2部分 构建抽象 229
第5章 宏 229
宏到底是什么? 229
宏不是什么 231
有什么是宏能做而函数不能做的 232
宏vs.Ruby的eval 234
编写你的第一个宏 235
调试宏 237
宏扩展 237
语法 240
引述和语法引述 240
反引述与编接反引述 241
什么时候使用宏 243
宏卫生 245
Gensym来拯救 246
让宏的用户来选择名字 249
重复求值 249
宏的常见用法和模式 251
隐藏参数:&env和&form 252
&env 253
&form 254
测试上下文相关的宏 259
深入->和->> 261
总结 264
第6章数据类型和协议 265
协议 266
扩展已有的类型 268
定义你自己的类型 272
记录 274
类型 280
实现协议 282
内联实现 284
重用实现 287
协议自省 291
协议函数分派的边界场景 292
自己实现一个set 294
总结 302
第7章 多重方法 303
多重方法基础 303
通往层级之路 306
层级 308
独立层级 310
真正实现多重! 313
还有几件事 315
多重继承 315
内省多重方法 316
type或class;或者说,映射的报复 316
转发函数的范围是无限的 318
最后的思考 319
第3部分工具、平台以及项目 323
第8章Clojure项目的组织与构建 323
项目布局 323
定义与使用命名空间 323
位置、位置、位置 334
Clojure代码库的功能组织 335
构建 337
提前编译 338
依赖管理 340
Maven的依赖管理模型 340
构建工具与配置模式 345
最后的思考 353
第9章Java及JVM互操作 355
JVM是Clojure的基础 356
Java类、方法和字段的使用 356
便利的互操作工具 359
异常与错误处理 361
摆脱检查型异常 363
with-open:finally的挽歌 364
为了效率进行类型提示 365
数组 369
定义类、实现接口 370
匿名类的实例:proxy 370
定义具名的类 373
注解 380
在Java里使用Clojure 384
使用deftype和defrecord类 386
实现协议接口 389
乐于合作的伙伴 391
第10章面向REPL的编程 393
交互式开发 393
持续、演化的环境 397
工具集 398
最简的REPL 399
Eclipse 402
Emacs 405
在REPL里调试、监测和打补丁 410
“已部署”REPL的特别考虑 412
重定义结构的限制 413
小结 415
第4部分实战 419
第11章数字与数学 419
Clojure中的数字 419
Clojure首选64比特(或更大)的表示 420
Clojure的混合数字模型 420
有理数 422
数字传播规则 423
Clojure中的数学 425
有限与任意精度 425
无检查的操作 428
任意精度的小数操作的刻度和取整模式 429
相等与等值 430
对象相同(identical?) 431
引用相等(=) 431
数字等值(=) 432
优化数字效率 434
声明函数接受和返回原始类型 435
合理使用原始类型的数组 439
用Clojure可视化芒德布罗集 447
第12章设计模式 455
依赖注入 457
策略模式 460
责任链 462
面向方面的编程 464
最后的思考 468
第13章测试 469
不可变值与纯函数 469
模拟 470
clojure.test 471
定义测试 472
测试“套件” 475
Fixtures 477
HTML DSL的成长 480
依赖断言 484
前条件和后条件 486
第14章使用关系数据库 489
clojure.java.jdbc 489
with-query-results解析 492
事务 494
连接池 494
Korma 496
前奏 496
查询 497
为什么不嫌麻烦地用DSL? 498
Hibernate 501
设置 501
持续数据 504
运行查询 505
去掉样板 506
最后的思考 507
第15章 使用非关型数据库 509
安装CouchDB和Clutch 510
基本的CRUD操作 510
视图 512
一个简单的(JavaScript)视图 512
用Clojure写的视图 514
_ changes:把CouchDB滥用做消息队列 517
可随意点选的消息队列 519
最后的思考 522
第16章Clojure与Web 523
Clojure栈 523
基石:Ring 524
请求与应答 525
适配函数 527
处理函数 528
中间件 529
用Compojure路由请求 531
使用模板 541
Enlive:基于选择器的HTML转换 542
最后的思考 550
第17章部署Clojure Web应用程序 551
Java与Clojure Web架构 551
Web应用程序打包 554
在本地运行Web应用 559
Web应用程序部署 560
在Amazon的 Elastic Beanstalk上部署Clojure应用 560
超越简单Web应用程序部署 563
第5部分杂项 567
第18章明智地选择Clojure类型定义形式 567
第19章在工作场所引进Clojure 571
事实是 571
强调生产效率 573
强调社区 574
审慎 575
第20章下一步? 577
(dissoc Clojure’JVM) 577
ClojureCLR 577
ClojureScript 578
4Clojure 578
Overtone 578
core.logic 579
Pallet 580
Avout 580
Heroku上的Clojure 581
索引 583