1. 保护式(guard)中如果出错,不会报错,只会返回false!
case 1=:1 of
true when not erlang:length(t) =:= 1 orelse true ->
ok;
_ ->
error
end.
Result is: error
保护式中对t (atom)
求length会出错,本应crash掉,但因为在保护式中,默认出错后结束此保护式计算并返回false,这也是为什么保护式不接受复杂的函数,只能用erlang的bif来做的原因之一。
2. try catch 时如果不写catch类型,默认为throw类型!
try_catch(Value) ->
try
case Value of
error -> erlang:error({error,plz_catch_me});
throw -> erlang:throw({throw,oh_get_you});
exit -> erlang:exit({exit,sorry_by_mistake})
end
catch
T -> T
end.
Result :
所以最好是:明确: Catch throw:T –> {throw,T}; error:T –> {error,T};
exit:T –> {exit,T} end.
3. 在保护式中使用erlang:length/1要小心再小心!(要遍历列表,时间长度不定)
%%写成这样的耗时与列表长度成平方比:Do not do this
foo(List) when lenght(List) >0 ->
do_something;
foo(_) ->
done.
%%使用匹配模式来做可做到任意长度断定
better([One]) ->
do_something_one();
better([One,Two]) ->
do_something_two();
better([one,Two|_]) ->
do_something_big();
better([]) ->
do_something_empty()
end.
Tip: 如果要判定List是一个非空List 可用 case List of [_|_] –> do_something(); _
–> done end.
4. ++只是lists:append/2的一个别名:如果要用一定要确定 ShortList++LongList
!(可记为长短的反义短长…每次用他我都会条件反射想一下)
%% DO NOT DO
naive_reverse([H|T]) ->
naive_reverse(T)++[H];
naive_reverse([]) ->
[].
which is the most inefficient way there is to reverse a list. Since the ++
operator copies its left operand, the result will be copied again and again and
again... leading to quadratic complexity.
这是最没效率去反转一个list,”++“会复制左边的元素,这个会使复制多次,导致平方倍的复杂度。
但是另一方面:下面这种用法就好了:
%% OK
naive_but_ok_reverse([H|T], Acc) ->
naive_but_ok_reverse(T, [H]++Acc);
naive_but_ok_reverse([], Acc) ->
Acc.
这并不是一个是非常坏的尝试,每个列表元素只被copy一次,那增长的Acc是在++的右边的,他不会每次都被copy的
当然,最佳实践还是下面这种:
%% Best Do
vanilla_reverse([H|T], Acc) ->
vanilla_reverse(T, [H|Acc]);
vanilla_reverse([], Acc) ->
Acc.
这比上面的还要高效一点点,你根本不用去建造一个list元素,直接copy他就可以了(或者:如果编译器不把[H]++Acc重写为[H|Acc]
,那就更高效啦)。
5. receive 和case的区别很大,虽然写法类似:
case_test(Value) ->
case Value of
1 -> ok;
2 -> error
end.
receive_test(Value)when Value>2 ->
PID = spawn(fun () ->
receive
{msg,1} ->
ok;
{msg,2} ->
error
end
end),
[begin PID ! {msg,ValueT} end ||ValueT<-lists:seq(3,Value)],
PID.
Result:
从上面可以看出:
5.1 case如果没有匹配就会出错;
5.1 recieve
会在没有匹配消息时阻塞,只要信箱中没有匹配消息,就会在等待期间挂起,=有新消息到时才会被唤醒,每次执行时,receive会先检查最老的消息(位于队列头部),像在case表达式中那样尝试匹配,如果找不到,就会继续下一消息,如果与当前匹配成功,且保护式成立(如果有),此消息就会被移出信箱,同时子句对应的正文会被执行,如果一直没找到合适消息就会一直等待至超时(如果有的话,after
Times).