整理了最近一段时间记录的Erlang代码片段,还有大量简短的代码都已经整理在官方文档的PDF中.从开始学习Erlang,写的测试代码都会整理到PDF中,从这个习惯中得益匪浅.可以在PDF上做批注,图形的工具我用的是:PDF-XChange Viewer
上一次代码片段整理:[Erlang 0043] Erlang Code Snippet
record 转 proplist
%% @spec record_to_proplist(Record, Fields) -> proplist() %% @doc calls record_to_proplist/3 with a default TypeKey of '__record' record_to_proplist(Record, Fields) -> record_to_proplist(Record, Fields, '__record'). %% @spec record_to_proplist(Record, Fields, TypeKey) -> proplist() %% @doc Return a proplist of the given Record with each field in the %% Fields list set as a key with the corresponding value in the Record. %% TypeKey is the key that is used to store the record type %% Fields should be obtained by calling record_info(fields, record_type) %% where record_type is the record type of Record record_to_proplist(Record, Fields, TypeKey) when tuple_size(Record) - 1 =:= length(Fields) -> lists:zip([TypeKey | Fields], tuple_to_list(Record)).
测试代码:
Eshell V5.9 (abort with ^G)
1> rd(person,{name,id,age}).
person
2> mochiweb_util:record_to_proplist(#person{}, record_info(fields, person)).
[{'__record',person},
{name,undefined},
{id,undefined},
{age,undefined}]
3> mochiweb_util:record_to_proplist(#person{age=12,name=zen,id=2396}, record_info(fields, person)).
[{'__record',person},{name,zen},{id,2396},{age,12}]
4>
1> rd(person,{name,id,age}).
person
2> mochiweb_util:record_to_proplist(#person{}, record_info(fields, person)).
[{'__record',person},
{name,undefined},
{id,undefined},
{age,undefined}]
3> mochiweb_util:record_to_proplist(#person{age=12,name=zen,id=2396}, record_info(fields, person)).
[{'__record',person},{name,zen},{id,2396},{age,12}]
4>
当然也可以这样:
Eshell V5.9 (abort with ^G) 1> rd(person,{name,id,age,blog,addr}). person 2> record_info(size,person). 6 3> record_info(fields,person). [name,id,age,blog,addr] 4> 4> P=#person{name="zen",id=1234,age=28,blog="me_sa",addr="beijing"}. #person{name = "zen",id = 1234,age = 28,blog = "me_sa", addr = "beijing"} 5> lists:zip(record_info(fields, person), tl(tuple_to_list(P))). [{name,"zen"}, {id,1234}, {age,28}, {blog,"me_sa"}, {addr,"beijing"}] 6> lists:zip(record_info(fields, person), tl(tuple_to_list(#person{}))). [{name,undefined}, {id,undefined}, {age,undefined}, {blog,undefined}, {addr,undefined}] 7> lists:zip(record_info(fields, person), tl(tuple_to_list(#person{age=23}))). [{name,undefined}, {id,undefined}, {age,23}, {blog,undefined}, {addr,undefined}]
record proplists 转换
地址: https://github.com/hio/erlang-record_info/blob/master/src/record_info.erl
% ---------------------------------------------------------------------------- % record_info. % ---------------------------------------------------------------------------- % Copyright 2011 YAMASHINA Hio. All rights reserved. % License: BSD (2-clause) % ---------------------------------------------------------------------------- -module(record_info). -export([version/0]). -export([version_string/0]). -export([record_list/1]). -export([field_list/2]). -export([default_value/3]). -export([record_to_proplist/2]). -export([proplist_to_record/3]). % private. -export([parse_transform/2]). -type proplist() :: [{atom(), any()}]. -type a_record() :: tuple(). -type record_name() :: atom(). -type field_name() :: atom(). -spec version() -> {non_neg_integer(),non_neg_integer(),non_neg_integer(),non_neg_integer()}. version() -> {0,3,0,0}. -spec version_string() -> string(). version_string() -> {Major,Minor,Patch,Build} = version(), lists:flatten(io_lib:format("~p.~p.~p.~p", [Major,Minor,Patch,Build])). -spec record_list( Module :: module() ) -> [record_name()]. record_list(Module) -> Module:record_info(list). -spec field_list( RecordName :: record_name(), Module :: module() ) -> [field_name()]. field_list(RecordName, Module) -> Module:record_info({keys, RecordName}). -spec default_value( Key :: field_name(), RecordName :: record_name(), Module :: module() ) -> any(). default_value(Key, RecordName, Module) -> Module:record_info({value, RecordName, Key}). -spec parse_transform( Forms :: [erl_parse:abstract_form()], Opts :: [compile:option()] ) -> [erl_parse:abstract_form()]. parse_transform(Form, Opts) -> record_info_transform:parse_transform(Form, Opts). -spec record_to_proplist( Record :: a_record(), Module :: module() ) -> proplist(). record_to_proplist(Record, Module) -> [RecordName | Values] = tuple_to_list(Record), Keys = field_list(RecordName, Module), lists:zip(Keys, Values). -spec proplist_to_record( List :: proplist(), RecordName :: record_name(), Module :: module() ) -> a_record(). proplist_to_record(List, RecordName, Module) -> Keys = field_list(RecordName, Module), Values = [ case proplists:lookup(Key, List) of {_, Value} -> Value; none -> default_value(Key, RecordName, Module); Any -> erlang:error({badarg, Any}, [List, Module, RecordName]) end || Key <- Keys ], list_to_tuple([RecordName | Values]). % ---------------------------------------------------------------------------- % End of File. % ----------------------------------------------------------------------------
保证应用程序已经启动
%% @spec ensure_started(App::atom()) -> ok %% @doc Start the given App if it has not been started already. ensure_started(App) -> case application:start(App) of ok -> ok; {error, {already_started, App}} -> ok end.
解析IP地址 是否支持IP V6
%%判断是否支持IPV6 ipv6_supported() -> case (catch inet:getaddr("localhost", inet6)) of {ok, _Addr} -> true; {error, _} -> false end. 6> inet_parse:address("192.168.0.1"). {ok,{192,168,0,1}}
整形幂运算
%% @spec int_pow(X::integer(), N::integer()) -> Y::integer() %% @doc Moderately efficient way to exponentiate integers. %% int_pow(10, 2) = 100. int_pow(_X, 0) -> 1; int_pow(X, N) when N > 0 -> int_pow(X, N, 1). int_pow(X, N, R) when N < 2 -> R * X; int_pow(X, N, R) -> int_pow(X * X, N bsr 1, case N band 1 of 1 -> R * X; 0 -> R end).
测试代码:
2> math:pow(2,3).
8.0
3> test:int_pow(2,3).
8
8.0
3> test:int_pow(2,3).
8
向上取整
%% @spec int_ceil(F::float()) -> integer() %% @doc Return the ceiling of F as an integer. The ceiling is defined as %% F when F == trunc(F); %% trunc(F) when F < 0; %% trunc(F) + 1 when F > 0. int_ceil(X) -> T = trunc(X), case (X - T) of Pos when Pos > 0 -> T + 1; _ -> T end.
在Erlang Shell中生成随机字符串
2> F=fun(Len, AllowedChars) -> lists:foldl(fun(_, Acc) -> [lists:nth(random:uniform(length(AllowedChars)), AllowedChars)] ++ Acc end, [], lists:seq(1, Len)) end. #Fun<erl_eval.12.111823515> 3> F(4,"0123456789abcdefghijklmnopqrstuvwxyz"). "iyqf" 4> F(4,"0123456789abcdefghijklmnopqrstuvwxyz"). "owlb" 5> F(4,"0123456789abcdefghijklmnopqrstuvwxyz"). "75lh" 6> F(4,"0123456789abcdefghijklmnopqrstuvwxyz"). "7k5p" 7> F(4,"0123456789abcdefghijklmnopqrstuvwxyz"). "k0fg"
产生GUID
random_token() -> Term = term_to_binary({node(), make_ref()}), Digest = erlang:md5(Term), binary_to_hex(Digest). binary_to_hex(Bin) when is_binary(Bin) -> [oct_to_hex(N) || <<N:4>> <= Bin]. oct_to_hex(0) -> $0; oct_to_hex(1) -> $1; oct_to_hex(2) -> $2; oct_to_hex(3) -> $3; oct_to_hex(4) -> $4; oct_to_hex(5) -> $5; oct_to_hex(6) -> $6; oct_to_hex(7) -> $7; oct_to_hex(8) -> $8; oct_to_hex(9) -> $9; oct_to_hex(10) -> $a; oct_to_hex(11) -> $b; oct_to_hex(12) -> $c; oct_to_hex(13) -> $d; oct_to_hex(14) -> $e; oct_to_hex(15) -> $f.
测试代码:
1> test:random_token().
"db6f50cc40d54e338b0362c05d1b0295"
2> test:random_token().
"98b784e379dee8fa68ff863ba6c02cff"
3> test:random_token().
"7bc7db7cbab45025adaa02e28cc3972d"
4> test:random_token().
"0f794a8aed063184393bc5bb883f53bf"
5> test:random_token().
"4e18f2879d8d05e86445082bf4a46f19"
"db6f50cc40d54e338b0362c05d1b0295"
2> test:random_token().
"98b784e379dee8fa68ff863ba6c02cff"
3> test:random_token().
"7bc7db7cbab45025adaa02e28cc3972d"
4> test:random_token().
"0f794a8aed063184393bc5bb883f53bf"
5> test:random_token().
"4e18f2879d8d05e86445082bf4a46f19"
YA生成随机字符串
-define(SAFE_CHARS, {$a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l, $m, $n, $o, $p, $q, $r, $s, $t, $u, $v, $w, $x, $y, $z, $A, $B, $C, $D, $E, $F, $G, $H, $I, $J, $K, $L, $M, $N, $O, $P, $Q, $R, $S, $T, $U, $V, $W, $X, $Y, $Z, $0, $1, $2, $3, $4, $5, $6, $7, $8, $9, $_}). rngchars(0) -> ""; rngchars(N) -> [rngchar() | rngchars(N - 1)]. rngchar() -> rngchar(crypto:rand_uniform(0, tuple_size(?SAFE_CHARS))). rngchar(C) -> element(1 + C, ?SAFE_CHARS).
测试代码:
10> test:rngchars(6).
"vlrLnt"
11> test:rngchars(6).
"y_fvQ_"
12> test:rngchars(6).
"VpOg8w"
13> test:rngchars(6).
"YzTnps"
"vlrLnt"
11> test:rngchars(6).
"y_fvQ_"
12> test:rngchars(6).
"VpOg8w"
13> test:rngchars(6).
"YzTnps"
2012-07-14更新
- 移除首尾空格
1> string:strip(" hi this is erlang ! ").
"hi this is erlang !" - 格式化输出补零
7> io:format("~8..0B~n", [42]).
00000042
13> io:format("~10B~n", [73]).
73
ok - 格式化右侧Padding
8> io:format("~-6B~n", [1024]).
1024
ok
9> io_lib:format("~-6B~n", [1024]).
[["1024",32,32],"\n"] - 浮点数格式化输出
11> io:format("~.2f~n", [1/3]).
0.33
ok
12> 1/3.
0.3333333333333333
13> - 移除List重复的元素
15> lists:usort([18, 16, 17, 18, 16, 19, 14, 17, 19, 18]).
[14,16,17,18,19]
处理XML
- 解析处理XML
<shopping> <item name="bread" quantity="3" price="2.50"/> <item name="milk" quantity="2" price="3.50"/> </shopping>
打印输出总金额: $14.50
-include_lib("xmerl/include/xmerl.hrl"). -export([get_total/1]). get_total(ShoppingList) -> {XmlElt, _} = xmerl_scan:string(ShoppingList), Items = xmerl_xpath:string("/shopping/item", XmlElt), Total = lists:foldl(fun(Item, Tot) -> [#xmlAttribute{value = PriceString}] = xmerl_xpath:string("/item/@price", Item), {Price, _} = string:to_float(PriceString), [#xmlAttribute{value = QuantityString}] = xmerl_xpath:string("/item/@quantity", Item), {Quantity, _} = string:to_integer(QuantityString), Tot + Price*Quantity end, 0, Items), io:format("$~.2f~n", [Total]).
- Erlang 动态创建XML
Given the following CSV:
bread,3,2.50
milk,2,3.50
Produce the equivalent information in XML, e.g.:
<shopping> <item name="bread" quantity="3" price="2.50" /> <item name="milk" quantity="2" price="3.50" /> </shopping>
to_xml(ShoppingList) -> Items = lists:map(fun(L) -> [Name, Quantity, Price] = string:tokens(L, ","), {item, [{name, Name}, {quantity, Quantity}, {price, Price}], []} end, string:tokens(ShoppingList, "\n")), xmerl:export_simple([{shopping, [], Items}], xmerl_xml).
好代码,一次擦肩而过可能就再也见不到了哦