休假回来,调整一下状态,先把Evernote里面一些比较零散的东西整理出来;过去一个月对于Erlang开发者还是有些惊喜的,比如《Erlang/OTP并发编程实战》终于出版了;比如<Building.Web.Applications.with.Erlang>也可以看到英文版了.下面第一条消息就是关于Erlang的另外一本好书:《Learn You Some Erlang》
Learn You Some Erlang 两则
Erlang学习有一个非常棒的网站: http://learnyousomeerlang.com/
现在有两则关于它的消息:
[1] 首先是这本书的Kindle版本, 能够在移动设备上阅读这本书,真的是非常方便;其实不仅仅是Kindle 其它支持mobi格式的都可以完美显示;甚至你可以使用源文件自己编译成为其它格式,比如epub;
github地址:https://github.com/igstan/learn-you-some-erlang-kindle
[2] 这个网站的出版物已经发行,其中文版由 @淘宝褚霸 翻译,可以预见到这又将成为中文资料的经典之作
http://book.douban.com/subject/10822017/
string To Erlang Term 一个更为考虑更为完善的方法
下面是可以解决的:
1> E=fun(S) ->{ok,Scanned,_} = erl_scan:string(S), {ok,Parsed} = erl_parse:parse_exprs(Scanned), erl_eval:exprs(Parsed,[]) end. #Fun<erl_eval.6.111823515> 2> E("{quit,tom}\n"++"."). {value,{quit,tom},[]} 3>
如果是Pid的情况下会存在异常
** exception error: no match of right hand side value {error,{1,erl_parse,["syntax error before: ","'<'"]}}
然后我在这里发现了一个更为完善的做法
https://github.com/erlang/otp/blob/master/lib/tv/src/tv_db_search.erl
string_to_term(Str) -> case catch erl_scan:string(Str ++ ". ") of {ok, ScannedStr, _No} -> case erl_parse:parse_term(ScannedStr) of {ok, Term} -> {ok, Term}; _Other -> %% May be a PID, have to check this, since erl_scan %% currently cannot handle this case... :-( case catch list_to_pid(Str) of Pid when is_pid(Pid) -> {ok, Pid}; _Error -> case get(error_msg_mode) of normal -> {error, {not_a_term, "Please enter a valid term!"}}; haiku -> {error, {not_a_term, ["Aborted effort.", "Reflect, repent and retype:", "Enter valid term."]}} end end end; _Error -> case get(error_msg_mode) of normal -> {error, {not_a_term, "Please enter a valid term!"}}; haiku -> {error, {not_a_term, ["Aborted effort.", "Reflect, repent and retype:", "Enter valid term."]}} end end.
binary 替换一例 注意转义符的使用
这个没有什么特别的,只是要注意转义字符的使用
85> binary:replace(<<"c:\\windows\\abc\\c.txt">>,<<92>>,<<"//">>,[global]). <<"c://windows//abc//c.txt">> 86> binary:replace(<<"c:\\windows\\abc\\c.txt">>,<<"\\">>,<<"//">>,[global]). <<"c://windows//abc//c.txt">> 87>
ETS表中,根据表名获取ets表id,可用但是繁琐一点
12> Fun3=fun(Name)->[ ID|| ID <-ets:all(),Name==ets:info(ID,name)] end. #Fun<erl_eval.6.111823515> 13> Fun3(inet_db). [inet_db] 14> Fun3(code). "\r" 15> Fun3(code_names). [4110] 16>
多个条件组合判断代码风格 2012-11-08 13:34 更新
多个条件的组合判断容易case套case 嵌套很多层 ,在Rabbitmq上看到一种代码风格比较不错
%% Wipe mnesia if we're changing type from disc to ram case {is_disc_node(), should_be_disc_node(ClusterNodes)} of {true, false} -> rabbit_misc:with_local_io( fun () -> error_logger:warning_msg( "changing node type; wiping " "mnesia...~n~n") end), rabbit_misc:ensure_ok(mnesia:delete_schema([node()]), cannot_delete_schema); _ -> ok end,
erlang模块下面有一个非常好用的解包方法
下面的解析可以使用string或binary模块自行解析,其实使用erlang:packet直接可以得到结果
Eshell V5.9.1 (abort with ^G) 1> erlang:decode_packet(http,<<"GET http://www.google.com HTTP/1.1\n">>,[]). {ok,{http_request,'GET', {absoluteURI,http,"www.google.com",undefined,"/"}, {1,1}}, <<>>} 2> erlang:decode_packet(1,<<3,"abcd">>,[]). {ok,<<"abc">>,<<"d">>} 3> erlang:decode_packet(1,<<5,"abcd">>,[]). {more,6} 4>
erlang:decode_packet的官方文档地址:http://www.erlang.org/doc/man/erlang.html
Erlang字符串处理的两个开源项目
[1] http://code.google.com/p/starling/
Unicode strings for Erlang
Starling is a Unicode string library for Erlang based on ICU, the best implementation of Unicode.
It's implemented as a C pipe driver packaged as an OTP application. Strings are stored as binaries internally. Compatibility layer with the standard string module is provided.
A mailing list has been set up at http://groups.google.com/group/starling-discuss.
The project homepage is at http://12monkeys.co.uk/starling.
[2]https://github.com/beerriot/icu4e icu4e: Erlang NIF wrappers around icu4c
Eshell V5.9 (abort with ^G) 1> self(). <0.30.0> 2> erlang:error(test_not_ok). ** exception error: test_not_ok 3> self(). <0.33.0> 4> catch erlang:error(test_not_ok). {'EXIT',{test_not_ok,[{erl_eval,do_apply,6, [{file,"erl_eval.erl"},{line,576}]}, {erl_eval,expr,5,[{file,"erl_eval.erl"},{line,360}]}, {shell,exprs,7,[{file,"shell.erl"},{line,668}]}, {shell,eval_exprs,7,[{file,"shell.erl"},{line,623}]}, {shell,eval_loop,3,[{file,"shell.erl"},{line,608}]}]}}
validate_inet_option(mode, Value) when Value =/= list, Value =/= binary -> throw({error, {eoptions, {mode,Value}}}); validate_inet_option(packet, Value) when not (is_atom(Value) orelse is_integer(Value)) -> throw({error, {eoptions, {packet,Value}}}); validate_inet_option(packet_size, Value) when not is_integer(Value) -> throw({error, {eoptions, {packet_size,Value}}}); validate_inet_option(header, Value) when not is_integer(Value) -> throw({error, {eoptions, {header,Value}}}); validate_inet_option(active, Value) when Value =/= true, Value =/= false, Value =/= once -> throw({error, {eoptions, {active,Value}}}); validate_inet_option(_, _) -> ok.
-spec reset(I :: array_indx(), Array :: array()) -> array(). reset(I, #array{size = N, max = M, default = D, elements = E}=A) when is_integer(I), I >= 0 -> if I < N -> try A#array{elements = reset_1(I, E, D)} catch throw:default -> A end; M > 0 -> A; true -> erlang:error(badarg) end; reset(_I, _A) -> erlang:error(badarg). reset_1(I, E=?NODEPATTERN(S), D) -> I1 = I div S + 1, setelement(I1, E, reset_1(I rem S, element(I1, E), D)); reset_1(_I, E, _D) when is_integer(E) -> throw(default); reset_1(I, E, D) -> Indx = I+1, case element(Indx, E) of D -> throw(default); _ -> setelement(I+1, E, D) end.
2012-08-30 17:25更新
http://learnyousomeerlang.com/errors-and-exceptions
Note: It is important to know that the protected part of an exception can't be tail recursive. The VM must always keep a reference there in case there's an exception popping up.
Because the
try ... catch
construct without theof
part has nothing but a protected part, calling a recursive function from there might be dangerous for programs supposed to run for a long time (which is Erlang's niche). After enough iterations, you'll go out of memory or your program will get slower without really knowing why. By putting your recursive calls between theof
andcatch
, you are not in a protected part and you will benefit from Last Call Optimisation.Some people use
try ... of ... catch
rather thantry ... catch
by default to avoid unexpected errors of that kind, except for obviously non-recursive code with a result they don't care about. You're most likely able to make your own decision on what to do!
2012-09-06 更新
有个朋友"有四个分组,每个分组独立统计得分然后排行",这个有没有简单的做法?这个功能其实很容易实现,但他所定义的简单其实就是能不能用一两行代码实现,下面这两行矫揉造作的代码就可以实现他的需要,但是!但是这样写没有任何优势,一旦逻辑复杂或者想添加调试就让这个方法特别的庞杂,大多数时候我们还是要按照规矩的路子写代码.L=[{30,a},{40,b},{30,a},{40,b},{23,c},{12,c},{1,d},{100,d}].lists:foldl(fun({X,a}, [{A,a},{B,b},{C,c},{D,d}]) -> [{A+X,a},{B,b},{C,c},{D,d}] ; ({X,b},[{A,a},{B,b},{C,c},{D,d}])->[{A,a},{B+X,b},{C,c},{D,d}] ;({X,c},[{A,a},{B,b},{C,c},{D,d}])->[{A,a},{B,b},{C+X,c},{D,d}] ;({X,d},[{A,a},{B,b},{C,c},{D,d}])->[{A,a},{B,b},{C,c},{D+X,d}] end, [{0,a},{0,b},{0,c},{0,d}],L).2012-11-5 20:41:58更新虽然大部分调试都是在Centos完成,但是在windows中还是有运行的需求,有一个非常不方便的事情就是 如何让erlang运行主目录设置为当前目录,我通常用下面的方法:在当前目录添加一个erl.cmd的文件,里面只需要一句""c:\Program Files\erl5.8.2\bin\erl.exe" -sname n1",如果你已经将erlang配置到环境变量,就更简单了,只需要三个字母"erl"即可.今天在Ulf wiger博客学了一招:设置.erl的打开方式为erl.exe,然后双击任何一个文件就可以打开Erlang Shell,且pwd()一下发现,已经在当前目录了.