[Erlang11] 那些经历过的Erlang小坑11-20
11.每次重装系统时都会重新安装Erlang,Ubuntu安装sh秒杀一切.
https://gist.github.com/zhongwencool/11174620
12. Erlang Shell隐藏的小技巧:
f(). %%把所有绑定变量释放掉 f(Val). %%把Val变量释放掉 v(Line). %%把Line行函数重新执行一次 v(-1). %%把前一行的函数重新执行一次 rr(Module).%%把Module中的Record加载到Shell中,【超有用】 rr("*/*"). %%把在这个子目录下的所有Module里面的Record给加载到Shell里面 rp(Expression).%%把Expression的全部元素给打印到shell里面【超有用】rl(). %%列出所有已定义过的Record.rf(RecordName).%%不加载名为RecordName的Record
%%如果你的code加了debug_info信息【compile:file(Module,[debug_info])】你可以这样看源代码 {ok,{_,[{abstract_code,{_,AC}}]}} = beam_lib:chunks(Beam,[abstract_code]), io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]).
13. Erlang中有很多不可逆函数:比如 binary_to_list/1 , list_to_binary/1
> binary_to_list(list_to_binary([ <<1,2>>,<<3,4>>])).
[1,2,3,4]
这个坑有点深,踩过才知道!这还有个和binary一起的小Tip:
> <<"xyz","ets","bt">> =:= <<"xyzetsbt">>. true
binary居然是等价的。
14.在保护式里面 ,等价于andalso ;等价于orelse------[但是:不是完全相同,原因如下]
%%相同点:
right_age(X) when X >= 16, X =< 104 -> %% X>=16 andalso X =< 104 true; right_age(_) –> false.
不同点:
%%当Condition1异常出错时,还会去判断Condtion2,如果使用orelse则会直接返回false func() when Condition1 ; Condition2 –> ok; func() –> error.
可以和http://www.cnblogs.com/zhongwencool/p/3712909.html 第一条对比一下,理解更深哦。
15.如果你想在实践中使用二叉树,请看gb_tree.erl,不要再造不必要的轮子啦,【不过可以考虑用来做练习】
16. 在try catch 的异常处理中禁止使用尾递归:
因为在这个异常处理部分有一个保护机制,Erlang绝对相信异常处理是正常的,如果你在这里面使用尾递归,会出现以下情况:
1) 尾递归变死循环啦【项目实践中可能会发生的】;
2) 非常多的进程进入了这个异常中,这个尾递归处理的东西又非常复杂,VM运行长久后,block大量的进程和消耗内存
这样的结果是:内存耗尽或程序特别慢,关键你还是查找不到最后的crash的原因。
所以推荐:异常处理中只使用必要且简单的处理就行了。
17. 如果你想在Erlang中 kill一个进程:找到Pid后,exit(Pid,Reasno).【效果和kill一样啦】
大部分情况不会起作用!!!!!因为在项目里面你的进程如果合规范都是在监控树下的,如果被exit/2后还会被监控树自动重启啦,所以你要先把进程移除监控树!!!
supervisor:terminate_child(SupPid,Pid),
supervisor: delete_child(SupPid,Pid).
18. 2个进程可以双向连接和单向连接:
双向: link(Pid1,Pid2). 重复调用效果一样,也就是说对同2个进程无论调用多少次link,只要使用一次unlink(Pid1,Pid2)就解除连接
单向:erlang:monitor/2 erlang: demonitor/1
19. receive after Time
这个Time最大值是50*24*60*60*1000,当时间大于50天时,就会报错:
所以要把Time拆成小于最大值的列表:
normalize(Time) –> Limit = 49*24*60*60, [Time rem Limit | lists:duplicate(Time div Limit, Limit)].
然后如果时间列表不为空就不断减少列表并等待直到列表为空:
loop([T|Next]}) –> receive {Server, Ref, cancel} –> Server ! {Ref, ok} after T*1000 –> if Next =:= [] –> Server ! {done, S#state.name}; Next =/= [] –> loop(Next}) end end.
20. gen_server里面的handle_call/3 和handle_cast/2返回值都可以加个Timeout时间。
如果这个时间内没有处理完就会发出一个timeout信息:由handle_info处理,具体可见:http://www.cnblogs.com/zhongwencool/p/erlang_timer.html 里面的方法二。