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

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).

时间: 2024-07-30 10:11:06

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

[Erl_Question11] 那些经历过的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("*/*&qu

微信小程序的坑(持续更新中)

参与微信小程序开发有一段时间了,先后完成信息查询类和交易类的两个不同性质的小程序产品的开发:期间遇到各种各样的小程序开发的坑,有的是小程序基础功能不断改进完善而需要业务持续的适配,有的是小程序使用上的一些坑:下面针对小程序开发过程中遇到的一些坑跟大家分享,有些没有深究具体原因: 1.原生组件遮盖的问题 由于原生组件层级最高,即使设置了其z-index也于事无补:不能随意在其层级上展示信息,只能通过cover-view和cover-image组件(其实这两个组件也是原生组件)来进行遮盖: 例如,下

Xcode7.1与iOS9之坑 (持续更新)

前几天升级OS X EI Capitan 10.11.1, 以及Xcode7.1,正好赶上公司新产品上线,要做iOS9的适配,遇到各种坑,各种查资料,随之记录总结一下遇到的坑. 先说下要适配iOS9要做的事: 1.更改http为https 两种方案: 一.公司后台服务器更改; 二.作为开发者,可在Xcode暂时退回到http协议.  开发者更改方法如下: 1.在Info.plist中添加App Transport Security Settings (或NSAppTransportSecurit

golang 小知识-持续更新中

Go 的原生数据类型可以分为基本类型和高级类型,基本类型主要包含 string, bool, int 及 float 系列,高级类型包含 struct,array/slice,map,chan, func . 相比 Java,Python,Javascript 等引用类型的语言,Golang 拥有类似C语言的指针这个相对古老的特性.但不同于 C 语言,Golang 的指针是单独的类型,而不是 C 语言中的 int 类型,而且也不能对指针做整数运算.从这一点看,Golang 的指针基本就是一种引用

Java常见小知识点(持续更新...)

1.在什么场景下需要重写hashcode?HashMap的实现原理? 如果我们对equals()方法进行了重写,一般对hashcode进行重写,保证相同的对象返回相同的hash值 HashMap实际上是一个"链表散列"的数据结构,即数组和链表的组合 当我们向HashMap中put值的时候,先计算key的hash值,再根据hash值来计算出这个key在数组中的下标(通过hash与数组长度-1的位与运算,也正是因此,map长度都是2的次方,因为要保证length-1  都是 )如果数组该位

记录学习Appium踩过的一些坑(持续更新)

1.用模拟器调试脚本无任何问题,一连上真机就只是打开了APP,编译器也没报任何错误 我用的小米手机 解决方法: 将  USB调试(安全设置) 打开. 就相当于 打开了  模拟点击 一个操作 这是真的和手机型号有关,小米和vivo有那么一点点坑多 附上原文:https://blog.csdn.net/qq_28482369/article/details/80116851 原文地址:https://www.cnblogs.com/luobobobo/p/9340837.html

Python小知识点(持续更新)

1.Python2字符编码 #coding:utf-8 ''' 上面的代码将环境编码设置为utf-8,没有上面的代码,将使用环境默认编码,环境默认编码可由sys.getdefaultencoding()获得 ''' s = '中国' #s是utf-8格式的str,因为上面的代码将环境编码设置为utf-8 u = s.decode('utf-8') #u是unicode对象 s.encode('gbk') #等价于s.decode('utf-8').encode('gbk') ''' 在计算机内存

nginx(tengine)的一些小优化(持续更新)

1.nginx日志切割脚本 需求来源:nginx本身并没有日志切割的功能,由访问产生的大日志很难进行分析. 实现目的:每天对nginx日志进行切割,并备份至指定文件夹. 简要指令: mv /usr/local/tengine/logs/access.log /usr/local/tengine/logs/access-date.log kill -USER1 Nginx主进程号. 解释: 通过mv命令重命名日志,并且通过kill -USER1 nginx-id的命令,告诉nginx需要写新的日志

iOS--开发小技巧(持续更新)

// 模糊效果 UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]; UIVisualEffectView *test = [[UIVisualEffectView alloc] initWithEffect:effect]; test.frame = self.view.bounds; test.alpha = 0; [self.view addSubview:test]; _mytext =