内容简介
本书由Erlang之父JoeArmstrong编写,是毋庸置疑的经典著作。书中兼顾了顺序编程、并发编程和分布式编程,重点介绍如何编写并发和分布式的Erlang程序以及如何在多核CPU上自动加速程序,并深入地讨论了开发Erlang应用中至关重要的文件和网络编程、OTP、ETS和DETS等主题。第2版全新改写,反应了自第1版面世以来Erlang历经的所有变化,添加了大量针对初学者的内容,并在每章后都附上了练习题。
目录
- 第一部分为何用Erlang
- 第1章什么是并发2
- 1.1给并发建模2
- 1.1.1开始模拟3
- 1.1.2发送消息4
- 1.1.3接收消息4
- 1.2并发的益处4
- 1.3并发程序和并行计算机5
- 1.4顺序和并发编程语言6
- 1.5小结6
- 第2章Erlang速览7
- 2.1Shell7
- 2.1.1=操作符8
- 2.1.2变量和原子的语法8
- 2.2进程、模块和编译9
- 2.2.1在shell里编译并运行HelloWorld9
- 2.2.2在Erlangshell外编译9
- 2.3你好,并发10
- 2.3.1文件服务器进程10
- 2.3.2客户端代码13
- 2.3.3改进文件服务器14
- 2.4练习14
- 第二部分顺序编程
- 第3章基本概念16
- 3.1启动和停止Erlangshell16
- 3.1.1在shell里执行命令17
- 3.1.2可能出错的地方17
- 3.1.3在Erlangshell里编辑命令18
- 3.2简单的整数运算18
- 3.3变量19
- 3.3.1Erlang的变量不会变20
- 3.3.2变量绑定和模式匹配20
- 3.3.3为什么一次性赋值让程序变得更好21
- 3.4浮点数22
- 3.5原子22
- 3.6元组23
- 3.6.1创建元组24
- 3.6.2提取元组的值25
- 3.7列表26
- 3.7.1专用术语26
- 3.7.2定义列表27
- 3.7.3提取列表元素27
- 3.8字符串27
- 3.9模式匹配再探29
- 3.10练习30
- 第4章模块与函数31
- 4.1模块是存放代码的地方31
- 4.1.1常见错误33
- 4.1.2目录和代码路径33
- 4.1.3给代码添加测试33
- 4.1.4扩展程序34
- 4.1.5分号放哪里36
- 4.2继续购物36
- 4.3fun:基本的抽象单元39
- 4.3.1以fun作为参数的函数40
- 4.3.2返回fun的函数41
- 4.3.3定义你自己的控制抽象42
- 4.4简单列表处理42
- 4.5列表推导45
- 4.5.1Quicksort46
- 4.5.2毕达哥拉斯三元数组47
- 4.5.3回文构词48
- 4.6内置函数48
- 4.7关卡49
- 4.7.1关卡序列49
- 4.7.2关卡示例50
- 4.7.3true关卡的作用51
- 4.8case和if表达式52
- 4.8.1case表达式52
- 4.8.2if表达式53
- 4.9构建自然顺序的列表54
- 4.10归集器55
- 4.11练习56
- 第5章记录与映射组57
- 5.1何时使用映射组或记录57
- 5.2通过记录命名元组里的项58
- 5.2.1创建和更新记录59
- 5.2.2提取记录字段59
- 5.2.3在函数里模式匹配记录59
- 5.2.4记录是元组的另一种形式60
- 5.3映射组:关联式键?值存储60
- 5.3.1映射组语法60
- 5.3.2模式匹配映射组字段62
- 5.3.3操作映射组的内置函数63
- 5.3.4映射组排序64
- 5.3.5以JSON为桥梁64
- 5.4练习66
- 第6章顺序程序的错误处理67
- 6.1处理顺序代码里的错误67
- 6.2用try...catch捕捉异常错误69
- 6.2.1try...catch具有一个值69
- 6.2.2简写法70
- 6.2.3try...catch编程样例71
- 6.3用catch捕捉异常错误72
- 6.4针对异常错误的编程样式72
- 6.4.1改进错误消息72
- 6.4.2经常返回错误时的代码73
- 6.4.3错误可能有但罕见时的代码73
- 6.4.4捕捉一切可能的异常错误74
- 6.5栈跟踪74
- 6.6抛错要快而明显,也要文明75
- 6.7练习75
- 第7章二进制型与位语法76
- 7.1二进制型76
- 7.2位语法78
- 7.2.1打包和解包16位颜色78
- 7.2.2位语法表达式79
- 7.2.3位语法的真实例子81
- 7.3位串:处理位级数据85
- 7.4练习87
- 第8章Erlang顺序编程补遗88
- 8.1apply89
- 8.2算术表达式90
- 8.3元数91
- 8.4属性91
- 8.4.1预定义的模块属性91
- 8.4.2用户定义的模块属性93
- 8.5块表达式94
- 8.6布尔值94
- 8.7布尔表达式95
- 8.8字符集95
- 8.9注释95
- 8.10动态代码载入96
- 8.11Erlang的预处理器99
- 8.12转义序列99
- 8.13表达式和表达式序列100
- 8.14函数引用101
- 8.15包含文件101
- 8.16列表操作:++和--102
- 8.17宏102
- 8.18模式的匹配操作符104
- 8.19数字105
- 8.19.1整数105
- 8.19.2浮点数105
- 8.20操作符优先级106
- 8.21进程字典106
- 8.22引用108
- 8.23短路布尔表达式108
- 8.24比较数据类型108
- 8.25元组模块109
- 8.26下划线变量109
- 8.27练习110
- 第9章类型111
- 9.1指定数据和函数类型111
- 9.2Erlang的类型表示法113
- 9.2.1类型的语法113
- 9.2.2预定义类型114
- 9.2.3指定函数的输入输出类型114
- 9.2.4导出类型和本地类型116
- 9.2.5不透明类型116
- 9.3dialyzer教程117
- 9.3.1错误使用内置函数的返回值118
- 9.3.2内置函数的错误参数119
- 9.3.3错误的程序逻辑119
- 9.3.4使用dialyzer120
- 9.3.5干扰dialyzer的事物120
- 9.4类型推断与成功分型121
- 9.5类型系统的局限性123
- 9.6练习125
- 第10章编译和运行程序126
- 10.1改变开发环境126
- 10.1.1设置载入代码的搜索路径126
- 10.1.2在系统启动时执行一组命令127
- 10.2运行程序的不同方式128
- 10.2.1在Erlangshell里编译和运行128
- 10.2.2在命令提示符界面里编译和运行129
- 10.2.3作为Escript运行130
- 10.2.4带命令行参数的程序131
- 10.3用makefile使编译自动化132
- 10.4当坏事发生135
- 10.4.1停止Erlang135
- 10.4.2未定义(缺失)的代码135
- 10.4.3shell没有反应136
- 10.4.4我的makefile不工作137
- 10.4.5Erlang崩溃而你想阅读故障转储文件137
- 10.5获取帮助138
- 10.6调节运行环境138
- 10.7练习139
- 第三部分并发和分布式程序
- 第11章现实世界中的并发142
- 第12章并发编程145
- 12.1基本并发函数145
- 12.2客户端?服务器介绍147
- 12.3进程很轻巧151
- 12.4带超时的接收153
- 12.4.1只带超时的接收154
- 12.4.2超时值为0的接收154
- 12.4.3超时值为无穷大的接收155
- 12.4.4实现一个定时器155
- 12.5选择性接收156
- 12.6注册进程157
- 12.7关于尾递归的说明158
- 12.8用MFA或Fun进行分裂160
- 12.9练习160
- 第13章并发程序中的错误161
- 13.1错误处理的理念161
- 13.1.1让其他进程修复错误162
- 13.1.2任其崩溃162
- 13.1.3为何要崩溃162
- 13.2错误处理的术语含义163
- 13.3创建连接164
- 13.4同步终止的进程组164
- 13.5设立防火墙165
- 13.6监视166
- 13.7基本错误处理函数166
- 13.8容错式编程167
- 13.8.1在进程终止时执行操作167
- 13.8.2让一组进程共同终止168
- 13.8.3生成一个永不终止的进程169
- 13.9练习170
- 第14章分布式编程171
- 14.1两种分布式模型171
- 14.2编写一个分布式程序172
- 14.3创建名称服务器173
- 14.3.1第1阶段:一个简单的名称服务器173
- 14.3.2第2阶段:客户端在一个节点,服务器在相同主机的另一个节点174
- 14.3.3第3阶段:同一局域网内不同机器上的客户端和服务器175
- 14.3.4第4阶段:跨互联网不同主机上的客户端和服务器176
- 14.4分布式编程的库和内置函数177
- 14.4.1远程分裂示例178
- 14.4.2文件服务器再探180
- 14.5cookie保护系统181
- 14.6基于套接字的分布式模型182
- 14.6.1用lib_chan控制进程182
- 14.6.2服务器代码183
- 14.7练习185
- 第四部分编程库与框架
- 第15章接口技术188
- 15.1Erlang如何与外部程序通信188
- 15.2用端口建立外部C程序接口190
- 15.2.1C程序191
- 15.2.2Erlang程序193
- 15.2.3编译和链接端口程序195
- 15.2.4运行程序195
- 15.3在Erlang里调用shell脚本196
- 15.4高级接口技术196
- 15.5练习197
- 第16章文件编程198
- 16.1操作文件的模块198
- 16.2读取文件的几种方法199
- 16.2.1读取文件里的所有数据类型199
- 16.2.2分次读取文件里的数据类型200
- 16.2.3分次读取文件里的行202
- 16.2.4读取整个文件到二进制型中202
- 16.2.5通过随机访问读取文件203
- 16.3写入文件的各种方式205
- 16.3.1把数据列表写入文件206
- 16.3.2把各行写入文件207
- 16.3.3一次性写入整个文件207
- 16.3.4写入随机访问文件209
- 16.4目录和文件操作209
- 16.4.1查找文件信息210
- 16.4.2复制和删除文件211
- 16.5其他信息211
- 16.6一个查找工具函数212
- 16.7练习214
- 第17章套接字编程216
- 17.1使用TCP216
- 17.1.1从服务器获取数据216
- 17.1.2一个简单的TCP服务器219
- 17.1.3顺序和并行服务器222
- 17.1.4注意事项223
- 17.2主动和被动套接字224
- 17.2.1主动消息接收(非阻塞式)224
- 17.2.2被动消息接收(阻塞式)225
- 17.2.3混合消息接收(部分阻塞式)225
- 17.3套接字错误处理226
- 17.4UDP227
- 17.4.1最简单的UDP服务器与客户端227
- 17.4.2一个UDP阶乘服务器228
- 17.4.3UDP数据包须知230
- 17.5对多台机器广播230
- 17.6一个SHOUTcast服务器231
- 17.6.1SHOUTcast协议232
- 17.6.2SHOUTcast服务器的工作原理232
- 17.6.3SHOUTcast服务器的伪代码233
- 17.6.4运行SHOUTcast服务器234
- 17.7练习235
- 第18章用WebSocket和Erlang进行浏览236
- 18.1创建一个数字时钟237
- 18.2基本交互239
- 18.3浏览器里的Erlangshell240
- 18.4创建一个聊天小部件241
- 18.5简化版IRC244
- 18.6浏览器里的图形247
- 18.7浏览器?服务器协议249
- 18.7.1从Erlang发送消息到浏览器249
- 18.7.2从浏览器到Erlang的消息250
- 18.8练习251
- 第19章用ETS和DETS存储数据252
- 19.1表的类型252
- 19.2影响ETS表效率的因素254
- 19.3创建一个ETS表255
- 19.4ETS示例程序255
- 19.4.1三字母组合迭代函数256
- 19.4.2创建一些表257
- 19.4.3创建表所需的时间258
- 19.4.4访问表所需的时间258
- 19.4.5获胜者是……259
- 19.5保存元组到磁盘260
- 19.6其余操作262
- 19.7练习263
- 第20章Mnesia:Erlang数据库264
- 20.1创建初始数据库264
- 20.2数据库查询265
- 20.2.1选择表里的所有数据266
- 20.2.2从表里选择数据267
- 20.2.3从表里有条件选择数据268
- 20.2.4从两个表里选择数据(联接)268
- 20.3添加和移除数据库里的数据269
- 20.3.1添加行269
- 20.3.2移除行270
- 20.4Mnesia事务270
- 20.4.1中止事务271
- 20.4.2载入测试数据273
- 20.4.3do()函数273
- 20.5在表里保存复杂数据274
- 20.6表的类型和位置275
- 20.6.1创建表276
- 20.6.2常用的表属性组合277
- 20.6.3表的行为278
- 20.7表查看器278
- 20.8深入挖掘279
- 20.9练习279
- 第21章性能分析、调试与跟踪280
- 21.1Erlang代码的性能分析工具281
- 21.2测试代码覆盖281
- 21.3生成交叉引用283
- 21.4编译器诊断信息283
- 21.4.1头部不匹配284
- 21.4.2未绑定变量284
- 21.4.3未结束字符串284
- 21.4.4不安全变量284
- 21.4.5影子变量285
- 21.5运行时诊断286
- 21.6调试方法287
- 21.6.1io:format调试288
- 21.6.2转储至文件289
- 21.6.3使用错误记录器289
- 21.7Erlang调试器289
- 21.8跟踪消息与进程执行291
- 21.9Erlang代码的测试框架294
- 21.10练习295
- 第22章OTP介绍296
- 22.1通用服务器之路297
- 22.1.1Server1:基本的服务器297
- 22.1.2Server2:实现事务的服务器298
- 22.1.3Server3:实现热代码交换的服务器299
- 22.1.4Server4:事务与热代码交换301
- 22.1.5Server5:更多乐趣302
- 22.2gen_server入门304
- 22.2.1确定回调模块名304
- 22.2.2编写接口方法305
- 22.2.3编写回调方法305
- 22.3gen_server的回调结构308
- 22.3.1启动服务器308
- 22.3.2调用服务器308
- 22.3.3调用和播发309
- 22.3.4发给服务器的自发性消息310
- 22.3.5后会有期,宝贝310
- 22.3.6代码更改311
- 22.4填写gen_server模板311
- 22.5深入探索313
- 22.6练习313
- 第23章用OTP构建系统315
- 23.1通用事件处理316
- 23.2错误记录器318
- 23.2.1记录错误318
- 23.2.2配置错误记录器319
- 23.2.3分析错误323
- 23.3警报管理324
- 23.4应用程序服务器326
- 23.4.1质数服务器326
- 23.4.2面积服务器327
- 23.5监控树328
- 23.6启动系统331
- 23.7应用程序335
- 23.8文件系统组织方式336
- 23.9应用程序监视器337
- 23.10怎样计算质数338
- 23.11深入探索340
- 23.12练习341
- 第五部分构建应用程序
- 第24章编程术语344
- 24.1保持Erlang世界观344
- 24.2多用途服务器346
- 24.3有状态的模块348
- 24.4适配器变量349
- 24.5表意编程351
- 24.6练习353
- 第25章第三方程序354
- 25.1制作可共享代码存档并用rebar管理代码354
- 25.1.1安装rebar354
- 25.1.2在GitHub上创建一个新项目355
- 25.1.3在本地克隆这个项目355
- 25.1.4制作一个OTP应用程序356
- 25.1.5宣传你的项目356
- 25.2整合外部程序与我们的代码357
- 25.3生成依赖项本地副本358
- 25.4用cowboy构建嵌入式Web服务器359
- 25.5练习364
- 第26章多核CPU编程366
- 26.1给Erlang程序员的好消息367
- 26.2如何在多核CPU中使程序高效运行367
- 26.2.1使用大量进程368
- 26.2.2避免副作用368
- 26.2.3避免顺序瓶颈369
- 26.3让顺序代码并行370
- 26.4小消息,大计算372
- 26.5用mapreduce使计算并行化376
- 26.6练习380
- 第27章福尔摩斯的最后一案381
- 27.1找出数据的相似度381
- 27.2sherlock演示382
- 27.2.1获取并预处理数据382
- 27.2.2寻找最像给定文件的邮件383
- 27.2.3搜索指定作者、日期或标题的邮件385
- 27.3数据分区的重要性386
- 27.4给邮件添加关键词386
- 27.4.1词汇的重要性:TF*IDF权重387
- 27.4.2余弦相似度:两个权重向量的相似程度388
- 27.4.3相似度查询389
- 27.5实现方式概览389
- 27.6练习390
- 27.7总结391
- 附录AOTP模板392
- 附录B一个套接字应用程序398
- 附录C一种简单的执行环境413
书不太厚,也不薄,500多页,但是单纯附录就占了100+,Appendix F
Module and Function Reference,有凑页面的嫌疑。有仁兄打印了整本书,叠起来转头那么厚,其实后面那一部分没有什么必要去打印。
此书中规中矩,跟n年前的《Concurrent Programming in ERLANG》的构造比较相像,先是顺序化编程,然后异常处理,并发编程,分布式编程。新内容有文件编程,网络编程,ETS,DETS,Mnesia,OTP,外部接口(Port),还有一章'Programming Multicore CPUs',在这个多核时代特别显眼,里面构造了一个MapReduce的例子。另外一个亮点是在 Distributed Programming 这章,里面在Cookie Base的认证外,提供了一个lib_chan的库用于实现Socket-Based Distribution,并且用了一整章(IRC Lite)在lib_chan的基础上实现了一个简单的多人聊天。
此书定位于入门级,由于之前已经读过《Getting Started With Erlang》,《Erlang Reference Manual》,《OTP Design Principles》,还有《Concurrent Programming in ERLANG》的第一部分,因此此书带来的收益并不是太多,对于其他未接触过Erlang的程序员来说会更加适合。相比Ruby,Lua等语言,Erlang更像是一个平台,它提供了很多便利的工具来方便我们的开发,书中只是简单提了一下,希望接下来会有更加高级的Erlang书籍出炉。
个人认为精髓在于并发的思想:每个进程都有自己独立的记忆,通过相互沟通来改变记忆,进行协作。