Clojure 編程樂趣, 2/e (The Joy of Clojure, 2/e) Clojure编程乐趣(第2版)

福格斯 (Michael Fogus), 豪澤 (Chris Houser)

買這商品的人也買了...

商品描述

這既不是一本Clojure初學指南,也不是一本Clojure的編程操作手冊。本書通過對Clojure詳盡地探究,講述函數式的程序設計方式,幫助讀者理解和體會Clojure編程的樂趣,進而開發出優美的軟件。
全書分為6個部分共17章。第1部分是基礎,包括第1~3章,從Clojure背後的思想開始,介紹了Clojure的基礎知識,並帶領讀者初步嘗試Clojure編程。第2部分是第4章和第5章,介紹了Clojure的各種數據類型。第3部分是第6章和第7章,介紹了函數式編程的特性。第4部分是第8章~11章,分別介紹了宏、組合數據域代碼、Clojure對Java的調用,以及並發編程等較為高級的話題。第5部分為第12章和第13章,探討了Clojure的性能問題及其帶給我們的思考。第6部分為第14~17章,介紹了面向數據編程、性能、思考程序以及Clojure的思考方式。
本書適合想要轉向函數式語言或進行並發編程的程序員閱讀,對JVM平臺編程感興趣的程序員,想要學習中高級的Java程序以及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.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部分數據類型

 

第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部分函數式編程

 

第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.4小結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部分大規模設計

 

第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使用promis e的時機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部分宿主共生關係

 

第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裡使用 
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. Collect ion 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部分雜項考量

 

第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的缺陷372 
15.6.7整合reducible到Clojure reduce 373 
15.6.8 fold函數:並行的reduce 374 
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