休假回來,調整一下狀態,先把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()一下發現,已經在當前目錄了.