整理了最近一段时间记录的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> 
 
当然也可以这样:
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
 
向上取整

%% @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 &lt; 0;
%%       trunc(F) + 1 when F &gt; 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"
 
 
 
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"
 
2012-07-14更新
 
  1. 移除首尾空格 
    1> string:strip("  hi  this is erlang !  ").
    "hi  this is erlang !"

  2. 格式化输出补零
    7> io:format("~8..0B~n", [42]).
    00000042
    13> io:format("~10B~n", [73]).
            73
    ok

  3. 格式化右侧Padding
    8> io:format("~-6B~n", [1024]).
    1024
    ok
    9> io_lib:format("~-6B~n", [1024]).
    [["1024",32,32],"\n"]

  4. 浮点数格式化输出
    11> io:format("~.2f~n", [1/3]).
    0.33
    ok
    12> 1/3.
    0.3333333333333333
    13>

  5. 移除List重复的元素
    15> lists:usort([18, 16, 17, 18, 16, 19, 14, 17, 19, 18]).
    [14,16,17,18,19]

处理XML

  1. 解析处理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]).

     

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

     

 
 
好代码,一次擦肩而过可能就再也见不到了哦