=:= =/=精确比较运算不仅比较值,还比较类型,效率更高
Erlang GC的特点是:每个进程独立进行GC ,分代(generational garbage) ,复制回收
Erlang的模式匹配作用:1.变量赋值 2.提取变量值 3.控制流
写function的时候在最后添加一个catch_all的方法也被认为是最佳实践
如果可预见结果集的所有可能性,那么case语句不建议使用catch_all
if语句会对Guard子句做catch,所以 if 1/0 ->a; true ->b end.的返回值是b而不是抛出异常
if的Guard子句放在变量里就可以让异常抛出来:G=1/0 , if G->a; true ->b end.
Guard subexpressions resulting in a runtime error are treated as returning false.
Guard可以使用, ; 表达多个条件if X=:=1,Y<2;X+Y<4 ->ok; true ->error end.
process dictionary几乎被描述成洪水猛兽了,对于一次写入然后就只读的配置性数据放在进程字典应该没有问题
Erlang出错法则:让错误报告在它发生的地方
查看module的元数据信息 比如a.erl a:module_info(). m(a).
Erlang的元编程Meta Programming确实直接,apply/3 甚至在参数确定情况下的直接调用M:F(A)
Concurrency is the ability for different functions to execute in parallel without affecting each other unless explicitly programmed to do so.
我们要遍历ETS可以使用first/next 也可以使用foldr foldl,但是后者会把ETS数据复制到进程,数据量大时有效率问题
负责进程创建职责的是Erlang VM中的Scheduler
spawn第三个参数是List,这个调用的时候注意!!
Spawning a process will never fail!!!
Sending a message will never fail!!!
receive子句的处理逻辑抽取为一个独立的方法是推荐的做法
receive如果接受到没有匹配任何子句的消息,那么这条消息就会保存在mailbox,长此以往就会耗尽内存系统崩溃之险;
消息发送的速度快于进程处理的速度就会增加CPU上的消耗,因为会反复扫描mailbox
Not handling unknown messages should therefore be treated as a bug. 匹配未知消息会导致难以发现错误,所以这些位置要记录日志
选择性接受和mailbox这两个东西就解决了消息接受缓冲区的问题
A race condition occurs when the behavior of a system depends on the order in which certain events occur: these events “race” to influence the behavior.
上面两个不失败的设计原则是为了解除进程依赖:另外一个进程的创建和接受消息是否成功不影响当前进程的正常执行
timer:tc/3计算方法的执行时间 这个构建简单的性能测试很方便
{'EXIT', Pid, Reason}退出消息的格式包含的信息:谁因为什么退出了
process_flag(trap_exit, true).退出截获的决策当然是在生命周期的早期进行配置。所以一般出现在init阶段。
截获到底做了一件什么事情呢?把退出消息放在进程收件箱中当成一个普通的消息来处理。这就相当于我们把异常信息放在返回结果中的情况
receive接收并处理退出信号,退出消息被截获就不再传播
link是双向的,monitor是单向的,被监控的进程死掉后,监控进程会收到 {'DOWN',Reference,process,Pid,Reason} 消息
如果接收到{'EXIT', Pid, Reason}的进程没有trap_exit,而且Reason不是normal,这个进程就会终止掉并继续传播这个退出消息
所有的BIFs的执行都是原子性的,所以spawn_link不等同于spawn 和 link的组合调用
{'EXIT', Pid, Reason}Reason如果是kill,关联进程无论是否trap_exit都会死掉
{'EXIT', Pid, Reason}Reason如果是normal,关联进程trap_exit会收到一条{'EXIT', Pid, normal}消息,如果没有trap_exit什么都不会发生
可以使用record_info()来查看record定义
ETS也是不参与GC的
Erlang是动态强类型的语言 dynamic-strong Typing
windows环境Erlang GUI工具:toolbar:start(). tv:start() pman:start(). appmon:start() debugger:start()
还有一个WebUI的工具 webtool:start().
Note: Using the form [1 | 2]
gives what we call an 'improper list'. Improper lists will work when you pattern match in the [Head|Tail]
manner, but will fail to be used with standard functions of Erlang (even length()
). This is because Erlang expects proper lists. Proper lists end with an empty list as their last cell. When declaring an item like[2]
, the list is automatically formed in a proper manner. As such, [1|[2]]
would work! Improper lists, although syntactically valid, are of very limited use outside of user-defined data structures.
在EShell中执行Erlang方法
$> erl -boot start_clean -noshell -eval 'io:format("hi\n")' -eval 'halt(0)'
% or
$> erl -boot start_clean -noshell -eval 'io:format("hi\n"), halt(0)'
% example:
erl -sname ad_service -eval 'ok=mnesia:create_schema([node()]).' -s init stop
打印浮点型
lists:flatten(io_lib:format("~.*..f", [2, S]));
3> lists:flatten(io_lib:format("~.*..f", [2, 192.2225])).
"192.22"
4> lists:flatten(io_lib:format("~.*..f", [3, 192.2225])).
"192.223"
5> lists:flatten([io_lib:format("~8.2.0B,", [L]) || L <- [1,2,3]]).
"00000001,00000010,00000011,"
6> lists:flatten([io_lib:format("~2.16.0B ", [L]) || L <- [1,2,3]]).
"01 02 03 ".
找出消耗内存最多的进程
lists:reverse(lists:keysort(2,[{P, erlang:process_info(P, heap_size)} || P <- erlang:processes()])).
找到最消耗内存的ETS表
lists:reverse(lists:keysort(2,[{T, ets:info(T, memory)} || T <- ets:all()])).
record类型作为参数的小技巧
-record(x,{name,zz}).
-record(y,{yy,name}).
-export([test1/0,test2/0]).
-define(create(Type,Name),#Type{name = Name}).
test1() -> ?create(x,"Noel"). % -> {x,"Noel",undefined}
test2() -> ?create(y,"Noel"). % -> {y,undefined,"Noel"}
binary_to_list VS bitstring_to_list
1> A = <<1:2, 23:6>>.
<<"W">>
2> B = <<1:2, 23:5>>.
<<55:7>>
3> binary_to_list(A).
"W"
4> binary_to_list(B).
** exception error: bad argument
in function binary_to_list/1
called as binary_to_list(<<55:7>>)
5> bitstring_to_list(A).
"W"
6> bitstring_to_list(B).
[<<55:7>>]
Erlang执行操作系统命令 os:cmd("uptime").
[3] or "3"
17> [51] =:= "3".
true
18> [3] =:= "3".
false
19>
如果仅仅是将一系列的模块打包在一起,并不需要启动application,那么只需要在app文件中移除掉{mod,{Module,Args}}配置节即可.这种Libiary Application典型范例就是stdlib.
看配置文件:
View Code
erlang:now常用作随机数的种子,这个并不是太好,建议使用:
4> <<A:32,B:32,C:32>> = crypto:strong_rand_bytes(12) .
<<42,136,117,238,28,89,154,241,88,189,70,139>>
5> b().
A = 713586158
B = 475634417
C = 1488799371
ok