內容簡介
Clojure是一門Lisp方言。它通過函式式編程技術,直接支持並發軟體開發,得到眾多開發人員的歡迎。
《Clojure編程樂趣》並非Clojure初學指南,也不是一本Clojure的編程操作手冊,而是通過對Clojure詳盡地探究,教授函式式的程式設計方式,幫助讀者理解和體會Clojure編程的樂趣,進而開發出優美的軟體。
全書分為5個部分共13章。第 1部分是基礎,包括第1章到第3章,從Clojure背後的思想開始,介紹了Clojure的基礎知識,並帶領讀者初步嘗試Clojure編程。第 2部分包括第4章和第5章,介紹了Clojure的各種數據類型。第3部分是第6章和第7章,介紹了函式式編程的特性。第4部分包括第8章到第 11章,分別介紹了宏、組合數據域代碼、Clojure對Java的調用,以及並發編程等較為高 級的話題。第5部分為第 12章和第 13章,探討了Clojure的性能問題及其帶給我們的思考。
《Clojure編程樂趣》適合有一定基礎的Clojure程式設計師閱讀,進而掌握函式編程的思考方法和程式設計方法,也可以作為讀者學習函式式編程的參考資料。
圖書目錄
第 1部分 基礎
第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.2.3 代碼即數據 11
1.3 函式式編程 11
1.3.1 一個可行的函式式編程定義 11
1.3.2 函式式編程的內涵 12
1.4 Clojure為何不是面向對象的 12
1.4.1 定義術語 12
1.4.2 命令式“烘烤” 14
1.4.3 OOP提供的大多數東西,Clojure也有 14
1.5 小結 18
第 2章 Clojure疾風式教程 19
2.1 標量 20
2.1.1 數字 20
2.1.2 整數 20
2.1.3 浮點數 21
2.1.4 有理數 21
2.1.5 符號 22
2.1.6 關鍵字 22
2.1.7 字元串 22
2.1.8 字元 22
2.2 組合起來:集合 23
2.2.1 list 23
2.2.2 vector 23
2.2.3 map 24
2.2.4 set 24
2.3 付諸實現:函式 24
2.3.1 調用函式 24
2.3.2 定義函式 25
2.3.3 用def和defn簡化函式定義 26
2.3.4 以#()定義原位(in-place)函式 27
2.4 var 27
2.5 局部量、循環和block 28
2.5.1 block 28
2.5.2 局部量 28
2.5.3 循環 29
2.6 防止發生:quote 31
2.6.1 求值 31
2.6.2 quote 32
2.6.3 反quote 34
2.6.4 反quote拼接 34
2.6.5 auto-gensym 35
2.7 與Java互操作 35
2.7.1 訪問靜態類成員 35
2.7.2 創建Java實例 35
2.7.3 用.運算符訪問Java實例成員 36
2.7.4 設定Java實例屬性 36
2.7.5 …宏 36
2.7.6 doto宏 37
2.7.7 定義類 37
2.8 異常環境 37
2.9 命名空間 38
2.9.1 用ns創建命名空間 38
2.9.2 用:require載入其他命名空間 39
2.9.3 用:use載入和創建映射 40
2.9.4 用:refer創建映射 41
2.9.5 用:import載入Java類 41
2.10 小結 41
第3章 小試牛刀 43
3.1 真值 44
3.1.1 什麼是真 44
3.1.2 不要創建布爾對象 44
3.1.3 nil vs. false 45
3.2 小心翼翼nil雙關 45
3.3 解構 46
3.3.1 你的任務,你應該選擇接受 47
3.3.2 解構vector 47
3.3.3 解構map 48
3.3.4 解構函式參數 50
3.3.5 解構vs.訪問器方法 50
3.4 用REPL做試驗 50
3.4.1 試驗seq 51
3.4.2 試驗圖形化 52
3.4.3 知識匯總 53
3.4.4 出錯之時 54
3.4.5 只為樂趣 55
3.5 小結 56
第 2部分 數據類型
第4章 標量 61
4.1 理解精度 62
4.1.1 截斷(Truncation) 62
4.1.2 提升(Promotion) 63
4.1.3 上溢(Overflow) 63
4.1.4 下溢(Underflow) 64
4.1.5 捨入錯誤(Rounding errors) 64
4.2 有理數 65
4.2.1 為什麼是有理數 65
4.2.2 怎樣才是有理數 66
4.2.3 有理數的合理性 67
4.3 使用關鍵字的時機 67
4.3.1 關鍵字與符號有怎樣的差別 68
4.3.2 限定關鍵字 69
4.4 符號解析 70
4.4.1 元數據 71
4.4.2 符號與命名空間 71
4.4.3 Lisp-1 72
4.5 正則表達式——第 二個問題 73
4.5.1 語法 73
4.5.2 函式 74
4.5.3 小心可變匹配器(matcher) 75
4.6 總結 75
第5章 組合數據類型 76
5.1 持久化、序列和複雜度 77
5.1.1 “你一直用著這個詞。我認為,這並不意味著它就是你以為的含義” 77
5.1.2 序列術語及其含義 78
5.1.3 大O 81
5.2 vector:創建和使用其各種變體 82
5.2.1 構建vector 82
5.2.2 大vector 83
5.2.3 vector當做棧 86
5.2.4 使用vector而非reverse 87
5.2.5 子vector 87
5.2.6 vector當做MapEntry 88
5.2.7 vector不是什麼 89
5.3 list:Clojure代碼form的數據結構 90
5.3.1 像Lisp那樣的list 90
5.3.2 list當做棧 91
5.3.3 list不是什麼 91
5.4 如何使用持久化佇列 91
5.4.1 什麼都沒有的佇列 92
5.4.2 入隊 93
5.4.3 獲取 93
5.4.4 出隊 93
5.5 持久化set 94
5.5.1 Clojure set的基本屬性 94
5.5.2 用sorted-set保持set的順序 95
5.5.3 contains 96
5.5.4 clojure.set 96
5.6 思考map 98
5.6.1 hash map 98
5.6.2 以有序map保持鍵值的順序 99
5.6.3 用數組map保持插入順序 101
5.7 知識匯總:在序列里查找某項的位置 101
5.8 小結 104
第3部分 函式式編程
第6章 惰性與不變性 107
6.1 關於不變性 107
6.1.1 定義不變性 108
6.1.2 固步自封—不變性 108
6.2 設計一個持久化玩具 110
6.3 惰性 113
6.3.1 以“邏輯與”熟悉惰性 113
6.3.2 理解lazy-seq的秘訣 115
6.3.3 丟掉頭 117
6.3.4 採用無限序列 118
6.3.5 delay和force宏 119
6.3.6 知識匯總:一個惰性的快速排序程式 121
6.4 小結 124
第7章 函式式編程 125
7.1 各種形式的函式 125
7.1.1 一等函式 126
7.1.2 高階函式 129
7.1.3 純函式 131
7.1.4 命名實參 132
7.1.5 使用前置條件和後置條件約束函式 133
7.2 閉包 135
7.3 遞歸思考 141
7.3.1 普通遞歸 141
7.3.2 尾遞歸和recur 143
7.3.3 勿忘trampoline 145
7.3.4 延續傳遞風格 147
7.4 知識匯總:A*尋路 149
7.4.1 A*實現 150
7.4.2 A*實現的筆記 153
7.5 小結 153
第4部分 大規模設計
第8章 宏 157
8.1 數據即代碼即數據 158
8.1.1 語法quote、反quote和拼接 159
8.1.2 宏之經驗談 160
8.2 定義控制結構 161
8.2.1 不用語法quote定義控制結構 161
8.2.2 使用語法quote和反quote定義控制結構 162
8.3 組合form的宏 163
8.4 使用宏改變form 165
8.5 使用宏控制符號解析 168
8.5.1 回指 169
8.5.2 (具有爭議地)有用的選擇性名字捕獲 170
8.6 使用宏管理資源 171
8.7 知識匯總:返回函式的宏 172
8.8 小結 175
第9章 組合數據與代碼 176
9.1 命名空間 176
9.1.1 創建命名空間 177
9.1.2 只暴露所需 179
9.1.3 聲明性包含和排除 181
9.2 以通用設計模式探索Clojure多重方法 182
9.2.1 組成部分 183
9.2.2 用法 184
9.2.3 以多重方法拯救 184
9.2.4 處理繼承行為的特別繼承 185
9.2.5 解析層次中的衝突 186
9.2.6 真正的**大功率任意分發 187
9.3 類型、協定和記錄 188
9.3.1 記錄 188
9.3.2 協定 191
9.3.3 用deftype從更原始的基礎開始構建 199
9.4 知識匯總:西洋棋移動的流暢構建器 201
9.4.1 Java實現 201
9.4.2 Clojure實現 203
9.5 小結 205
第 10章 Java.next 206
10.1 使用proxy動態生成對象 207
10.2 Clojure gen-class和GUI程式設計 211
10.2.1 命名空間作為類的規範 211
10.2.2 以Clojure探索用戶界面設計與開發 214
10.3 Clojure同Java數組的關係 217
10.3.1 數組的類型:原生與引用 217
10.3.2 數組可變性 219
10.3.3 那個不幸的命名約定 220
10.3.4 多維數組 221
10.3.5 調用可變方法/構造函式 221
10.4 所有Clojure函式都實現…… 222
10.4.1 java.util.Comparator 222
10.4.2 java.lang.Runnable 223
10.4.3 java.util.concurrent.Callable 223
10.5 在Java API里使用Clojure數據結構 224
10.5.1 java.util.List 224
10.5.2 java.lang.Comparable 225
10.5.3 java.util.RandomAccess 225
10.5.4 java.util.Collection 225
10.5.5 java.util.Set 226
10.6 definterface 227
10.7 慎用異常 229
10.7.1 一點異常的背景 229
10.7.2 運行時異常vs.編譯時異常 230
10.7.3 處理異常 231
10.7.4 定製異常 232
10.8 小結 233
第 11章 變化 234
11.1 軟體事務性記憶體,包括多版本並發控制和快照隔離 235
11.1.1 事務 235
11.1.2 嵌入式事務 237
11.1.3 STM使其簡單的事情 237
11.1.4 潛在缺陷 238
11.1.5 讓STM不高興的事 239
11.2 使用Ref的時機 240
11.2.1 使用alter進行可協調的、同步的改變 241
11.2.2 以commute進行可交換的改變 244
11.2.3 以ref-set進行普通改變 245
11.2.4 用ensure修正寫入偏差 245
11.2.5 壓力之下的Ref 246
11.3 使用Agent的時機 247
11.3.1 進程內並發模型vs分散式並發模型 248
11.3.2 用Agent控制I/O 249
11.3.3 send和send-off之間的差異 251
11.3.4 錯誤處理 252
11.3.5 何時不用Agent 254
11.4 使用Atom的時機 255
11.4.1 跨執行緒共享 255
11.4.2 在事務里使用Atom 256
11.5 使用lock的時機 258
11.5.1 使用鎖進行安全變化 259
11.5.2 使用Java的顯式鎖 260
11.6 使用future的時機 261
11.7 使用promise的時機 264
11.7.1 以promise進行並行任務 265
11.7.2 回調API到阻塞API 266
11.7.3 確定性死鎖 267
11.8 並行 267
11.8.1 pvalues 268
11.8.2 pmap 268
11.8.3 pcalls 269
11.9 var和動態綁定 269
11.9.1 binding宏 270
11.9.2 創建命名var 271
11.9.3 創建匿名var 272
11.9.4 動態作用域 273
11.10 小結 274
第5部分 雜項考量
第 12章 性能 277
12.1 類型提示 277
12.1.1 類型修飾的優勢 278
12.1.2 類型提示實參和返回值 278
12.1.3 類型提示對象 279
12.2 暫態(transient) 280
12.2.1 短暫的垃圾 280
12.2.2 暫態在效率上與可變集合相比較 280
12.3 分塊序列 282
12.4 記憶 283
12.4.1 記憶再研究 284
12.4.2 記憶協定 284
12.5 理解強制轉型(coercion) 287
12.5.1 強制轉型第 一原則:不要這么做 287
12.5.2 推論:我們可能沒做對 287
12.5.3 強制轉型第 二原則:不要這么做 289
12.5.4 強制轉型第三原則:強制轉型穩定的局部量 289
12.5.5 強制轉型第四原則:觀測大小 289
12.5.6 強制轉型第五原則:只在截取是目標時 289
12.6 小結 290
第 13章 Clojure改變我們的思考方式 291
13.1 DSL 292
13.1.1 無所不在的DSL 292
13.1.2 將括弧置於規範周圍 293
13.1.3 Clojure方式DSL的註記 296
13.2 測試 297
13.2.1 一些有用的技術 297
13.2.2 契約式程式設計 300
13.3 缺乏設計模式 301
13.4 錯誤處理和調試 304
13.4.1 錯誤處理 304
13.4.2 調試 306
13.5 珍重 310
附錄 資源 312
雜項資源 312
線上資源 317