码迷,mamicode.com
首页 > 其他好文 > 详细

[Erl_Question02] 那些经历过的Erlang小坑(持续更新)

时间:2014-05-07 11:16:50      阅读:304      评论:0      收藏:0      [点我收藏+]

标签:style   blog   class   code   java   color   

1. 保护式(guard)中如果出错,不会报错,只会返回false!

bubuko.com,布布扣
case 1=:1 of
     true when not erlang:length(t) =:= 1 orelse true ->
           ok;
     _ ->
         error
end.
Result is:   error
bubuko.com,布布扣

保护式中对t (atom) 求length会出错,本应crash掉,但因为在保护式中,默认出错后结束此保护式计算并返回false,这也是为什么保护式不接受复杂的函数,只能用erlang的bif来做的原因之一。

2. try catch 时如果不写catch类型,默认为throw类型!

bubuko.com,布布扣
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.
bubuko.com,布布扣

Result :

bubuko.com,布布扣

所以最好是:明确: Catch   throw:T –> {throw,T}; error:T –> {error,T}; exit:T –> {exit,T} end.

 

3. 在保护式中使用erlang:length/1要小心再小心!(要遍历列表,时间长度不定)

bubuko.com,布布扣
%%写成这样的耗时与列表长度成平方比: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.
bubuko.com,布布扣

Tip:  如果要判定List是一个非空List 可用 case List of [_|_] –> do_something(); _ –> done end.

4. ++只是lists:append/2的一个别名:如果要用一定要确定 ShortList++LongList !(可记为长短的反义短长…每次用他我都会条件反射想一下)

bubuko.com,布布扣
%% DO NOT DO
naive_reverse([H|T]) ->
    naive_reverse(T)++[H];
naive_reverse([]) ->
    [].
bubuko.com,布布扣

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,”++“会复制左边的元素,这个会使复制多次,导致平方倍的复杂度。

但是另一方面:下面这种用法就好了:

 
bubuko.com,布布扣
%% OK
naive_but_ok_reverse([H|T], Acc) ->
    naive_but_ok_reverse(T, [H]++Acc);
naive_but_ok_reverse([], Acc) ->
    Acc.
bubuko.com,布布扣

这并不是一个是非常坏的尝试,每个列表元素只被copy一次,那增长的Acc是在++的右边的,他不会每次都被copy的

当然,最佳实践还是下面这种:

bubuko.com,布布扣
%% Best Do
vanilla_reverse([H|T], Acc) ->
    vanilla_reverse(T, [H|Acc]);
vanilla_reverse([], Acc) ->
    Acc.
bubuko.com,布布扣

这比上面的还要高效一点点,你根本不用去建造一个list元素,直接copy他就可以了(或者:如果编译器不把[H]++Acc重写为[H|Acc] ,那就更高效啦)。

5. receive 和case的区别很大,虽然写法类似:

bubuko.com,布布扣
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.
bubuko.com,布布扣

Result:

bubuko.com,布布扣

从上面可以看出:

5.1 case如果没有匹配就会出错;

5.1 recieve 会在没有匹配消息时阻塞,只要信箱中没有匹配消息,就会在等待期间挂起,=有新消息到时才会被唤醒,每次执行时,receive会先检查最老的消息(位于队列头部),像在case表达式中那样尝试匹配,如果找不到,就会继续下一消息,如果与当前匹配成功,且保护式成立(如果有),此消息就会被移出信箱,同时子句对应的正文会被执行,如果一直没找到合适消息就会一直等待至超时(如果有的话,after Times).

[Erl_Question02] 那些经历过的Erlang小坑(持续更新),布布扣,bubuko.com

[Erl_Question02] 那些经历过的Erlang小坑(持续更新)

标签:style   blog   class   code   java   color   

原文地址:http://www.cnblogs.com/zhongwencool/p/3712909.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!