Erlang Programming 笔记 1
1. Erlang 优势
- 并发和分布式
- 主流语言使用共享内存模型,类似于
x = x + n
的代码导致了在多核环境下需要小心的处理锁的问题 - Erlang 使用消息模型,Process 间不共享数据,从而避免了锁的问题
- 无锁避免了顺序瓶颈,添加节点到网络更容易
- 主流语言使用共享内存模型,类似于
- 错误处理
- 多数语言默认认为程序不会出错
- Erlang 采用不同的设计决策——注定要出错,那就让他出错,出错后恢复就行了。即 Erlang 程序出错后,会交由更高级的 Process 来处理(重启 Child Process、系列全部终止、重启相关 Process 等等),从而实现对错误的分级和容错处理
- 同时带来了热更新的好处,进一步保证了可用性
2. 入门
Shell
f().
会释放所有绑定的变量- 崩溃文件分析
webtool:start().
原子
使用单引号括起来的字符也是原子
这使得原子可以以大写字母开头,或者带有空格
'a' = a. %a 'Monday'. 'an atom with spaces'.
列表
可以包含不同类型
访问列表的头是高效的,所以通常函数处理也从列表头取起
插入元素到列表头部是高效的
A = ["a","b"]. C = ["c","d" | A ]. % ["c","d","a","b"]
- 尽量避免使用
List ++ [H]
这样的操作,通常情况下添加元素到列表尾部是极为低效的(重新生成新的列表),只有在列表非常短的时候可以这样用 - 添加在头部然后使用
lists:reverse/1
反转通常比添加在列表尾部效率要高 - 尽量使用经过高度优化的 BIF ,比如反转列表
lists:reverse/1
,可以从源码中找到它的定义,但是这个定义通常是作为简单的声明,实际上编译器会使用这个函数在系统内部更为高效的版本
- 尽量避免使用
字符串
严格说来 Erlang 中并没有字符串
字符串实际上是整数列表的一种「速记/代表」形式
可用
$
来表示字符串的整数值A = $a. % 97
3. 顺序型编程
beam
beam 是 Bogdan’s Erlang Abstract Machine 的缩写匿名函数 fun
fun 也可以拥有多个子句
TempFun = fun ({square, X}) -> X*X; ({double,X}) -> X+X end.
列表解析
列表解析实现最简单的 Map
map(F, L) = [F(X) || X <- L].
列表解析中的生成器实际上也可以起到过滤的作用
[ X || {X, _} <- [ a,{c, d}, "aa", {"c", e}]]. % [ c, "c"]
快排算法
qsort([]) -> []; qsort([Pivot | T]) -> qsort([X || X <- T, X < Pivot]) ++ [H] ++ qsort([X || X <- T, X >= Pivot]).
毕达哥拉斯三元组
pythag(N) -> [{A, B, C} || A <- lists:seq(1, N), B <- lists:seq(1, N), C <- lists:seq(1, N), A + B + C =< N, A*A + B*B =:= C*C ].
全排列
perms([]) -> [[]]; perms(List) -> [ [H | T] || H <- L, T <- perms(L -- [H]) ].
断言
以 when 开头
用
;
隔开的断言,只要有一个为true
则断言序列成立用
,
隔开的断言,只有全部为true
断言才会成立合法的断言必须保证没有副作用,可以包含一些无副作用的 BIF ,但无法使用用户自定义的布尔表达式函数
and, or
和andalso, orelse
Erlang Guard: and/andalso, or/orelse==
和=:=
,/=
和=/=
=:=
代表精确等于,在比较的时候不会对数据类型进行转换=/=
代表精确不等于99% 的情况下应使用
=:=
或=/=
模式匹配中实际上是
=:=
,即f(12)
不会匹配到f(12.0)
1 == 1.0. % true 1 =:= 1.0。 %false
比较运算符的优先级
不同数据类型也可以比较大小,其优先级是:
number < atom < reference < fun < port < pid < tuple < list < binary
<<"1">> > ["2"]. % true ["2"] > {"3"}. % true {"3"} > 'atom'. % true atom > 1. % true
record
- Record 实际上只是 tuple 的「伪装」,其本质上是一个 tuple
case/if
- Erlang 中不存在多个 case 匹配一个执行块的语法
- Erlang 中任何表达式都是有值的,包括 case,因此可以有
X = case ... end
- Case 最后使用
_
, if 最后使用true
是保证所有分支得到匹配的方法
累加器
- 存储迭代过程中的临时容器