在使用Erlang开发过程中我们会积累一些常用的util方法,同时会把一些方便编译调试的方法放在Erlang的user_default模块.今天翻阅Evernote发现两段非常实用的代码片段,由于google codesearch服务已经关闭,源头不可追溯,好东西不可独享,和大家分享.
本文会持续更新补充内容.
 
-module(u).
-compile(nowarn_unused_function).
-compile(export_all).

trace(X) -> spawn(fun() -> io:format("~p~n",[X]) end).
trace(X,Y) -> spawn(fun() -> io:format("~p: ~p~n",[X,Y]) end).
traceBinary(X) -> spawn(fun() -> io:format("~p~n",[b2h(X)]) end).

for(Max, Max, F) -> [F(Max)];
for(I, Max, F) -> [F(I)|for(I+1, Max, F)].


b2h(Bin) -> lists:flatten([io_lib:format("~2.16.0B", [X]) || X <- binary_to_list(Bin)]).
h2b(String) -> << << (erlang:list_to_integer([Char], 16)):4/integer >> || Char <- String >>.
t(String)-> h2b(String).
txt(Bin) -> [X || <<X>> <= Bin,X > 32, X < 127, X =/= 45].
b2s(Bin) -> b2s1(binary_to_list(Bin),[]).
b2s1([],Str) -> lists:reverse(Str);
b2s1([H|T],Str) ->
case H > 32 andalso H < 127 andalso H =/= 45 of
true -> b2s1(T,[H|Str]);
false -> b2s1(T,[46,46|Str])
end.

pmap(F, L,Parent) -> [receive {Pid, Res} -> Res end || Pid <- [spawn(fun() -> Parent ! {self(), F(X)} end) || X <- L]].

timer(Time,Fun) -> spawn(fun() -> receive after Time -> ?MODULE:Fun() end end).


signSubtract(A,B) ->
case A<0 of
true -> (erlang:abs(A)-erlang:abs(B))*-1;
false -> (erlang:abs(A)-erlang:abs(B))
end.

signSubtract1(A,B) ->
case A<0 of
true -> (erlang:abs(A)-B)*-1;
_ -> (erlang:abs(A)-B)
end.

%% u:floor(-4.7).
%% Output: -5
floor(X) when X < 0 ->
T = trunc(X),
case (X - T) =:= 0 of
true -> T;
false -> T - 1
end;
floor(X) -> trunc(X).

%%添加协议头
addLen(Bin) ->
Len=erlang:size(Bin)+2,
<<Len:16,Bin/binary>>.
 

user_default

  [Erlang 0027] Using Record in Erlang Shell 一文中我们已经提到过user_default的用法,不过上次只是小试牛刀用来加载record的定义而已,看看下面的方法;注意这些方法可以直接在Erlang Shell中使用的哦
 
     Erlang doc link : http://www.erlang.org/documentation/doc-5.4.12/lib/stdlib-1.13.11/doc/html/shell.html

If a command (local function call) is not recognized by the shell, an attempt is first made to find the function in the module user_default, where customized local commands can be placed. If found, then the function is evaluated. Otherwise, an attempt is made to evaluate the function in the module shell_default. The module user_default must be explicitly loaded.

There is some support for reading and printing records in the shell. During compilation record expressions are translated to tuple expressions. In runtime it is not known whether a tuple actually represents a record. Nor are the record definitions used by compiler available at runtime. So in order to read the record syntax and print tuples as records when possible, record definitions have to be maintained by the shell itself. The shell commands for reading, defining, forgetting, listing, and printing records are described below. Note that each job has its own set of record definitions. To facilitate matters record definitions in the modules shell_default and user_default (if loaded) are read each time a new job is started.

-module(user_default).
-compile(export_all).

z(File) ->
Out=compile:file(["./src/", atom_to_list(File),".erl"],
[{outdir,"./ebin/"}, {i,"./src/"},report,debug_info ]),
lm(),
Out.

x(File) ->
Out=compile:file(["./test/", atom_to_list(File),".erl"],
[ {outdir,"./ebin/"}, {i,"./src/"},report,debug_info ]),
lm(),
Out.

s(App) ->
application:start(App).

r(App) ->
application:stop(App),
% os:cmd("ebin ./src/*.erl -I ./include/ +debug_info"),
make:all(),
make:all([load]),
lm(),
application:start(App).

zz(File) ->
?MODULE:z(File),
File:start().

xx(File) ->
?MODULE:x(File),
File:start().

rbb() ->
rb:start([{max,20}]).

rbb(Num) -> rb:start([{max,Num}]).

rbl() -> rb:list().

rbs(Num) ->
rb:show(Num).

test() ->
reloader:reload_modules(reloader:all_changed()).

ll() ->
make:all(),
lm().
lm() -> [c:l(M) || M <- mm()].
mm() -> modified_modules().
modified_modules() ->
[M || {M,_} <- code:all_loaded(), module_modified(M) == true].
module_modified(Module) ->
case code:is_loaded(Module) of
{file,preloaded} ->
false;
{file,Path} ->
CompileOpts = proplists:get_value(compile,Module:module_info()),
CompileTime = proplists:get_value (time,CompileOpts),
Src = proplists:get_value (source,CompileOpts),
module_modified (Path,CompileTime,Src);
_ -> false
end.

module_modified(Path,PrevCompileTime,PrevSrc) ->
case find_module_file(Path) of
false -> false;
ModPath -> case beam_lib:chunks(ModPath, ["CInf"]) of
{ok, {_, [{_, CB}]}} ->
CompileOpts = binary_to_term(CB),
CompileTime = proplists:get_value(time,CompileOpts),
Src = proplists:get_value(source,CompileOpts),
not (CompileTime == PrevCompileTime) and (Src == PrevSrc);
_ -> false
end
end.

find_module_file(Path) ->
case file:read_file_info(Path) of
{ok,_} -> Path;
_ -> % maybe path was changed
case code:where_is_file(filename:basename(Path)) of
non_existing -> false;
NewPath -> NewPath
end
end.
 
2012-11-20 09:28 更新 新增一版
 
-module(user_default).

-export([sync/0]).
-export([make/0]).
-export([git/1]).
-export([reload/0]).
-export([reload_then/1]).

-export([dbg/0]).
-export([dbg/1]).
-export([dbg/2]).
-export([dbg/3]).
-export([dbg/4]).

-export([tc_avg/4]).

-compile(inline).

%% Reload code
reload() ->
    LibExclude = base_lib_path(),
    Modules = [M || {M, P} <- code:all_loaded(), is_list(P) andalso string:str(P, LibExclude) =:= 0],
    [shell_default:l(M) || M <- Modules].

%% Reload code then exec F
reload_then(F) ->
    reload(),
    F().

%% Compiles all files in Emakefile and load into current shell.
sync() ->
    make:all([load]).

%% Run the make command in shell.
make() ->
    run_command(["make", "all"]).

%% Run git command in shell.
git(Command) ->
    CommandList = ["git", Command],
    run_command(CommandList).

dbg()                           -> dbg:tracer().

dbg(c)                          -> dbg:stop_clear();
dbg(M)                          -> dbge({M, '_', '_'}, []).

dbg(M, c)                       -> dbgc({M, '_', '_'});
dbg(M, r)                       -> dbge({M, '_', '_'}, dbg_rt());
dbg(M, l)                       -> dbgl({M, '_', '_'}, []);
dbg(M, lr)                      -> dbgl({M, '_', '_'}, dbg_rt());
dbg(M, F) when is_atom(F)       -> dbge({M,   F, '_'}, []);
dbg(M, O)                       -> dbge({M, '_', '_'}, O).

dbg(M, F, c)                    -> dbgc({M,   F, '_'});
dbg(M, F, l)                    -> dbgl({M,   F, '_'}, dbg_rt());
dbg(M, F, r)                    -> dbge({M,   F, '_'}, dbg_rt());
dbg(M, F, lr)                   -> dbgl({M,   F, '_'}, dbg_rt());
dbg(M, F, A) when is_integer(A) -> dbge({M,   F,   A}, []);
dbg(M, F, O)                    -> dbge({M,   F, '_'}, O).

dbg(M, F, A, c)                 -> dbgc({M,   F,   A});
dbg(M, F, A, r)                 -> dbge({M,   F,   A}, dbg_rt());
dbg(M, F, A, l)                 -> dbgl({M,   F,   A}, dbg_rt());
dbg(M, F, A, lr)                -> dbgl({M,   F,   A}, dbg_rt());
dbg(M, F, A, O)                 -> dbge({M,   F,   A}, O).

tc_avg(M, F, A, N) when N > 1 ->
    L = tl(lists:reverse(tc_loop(M, F, A, N, []))),
    Length = length(L),
    Min = lists:min(L),
    Max = lists:max(L),
    Med = lists:nth(round((Length / 2)), lists:sort(L)),
    Avg = round(lists:foldl(fun(X, Sum) -> X + Sum end, 0, L) / Length),
    io:format("Range: ~b - ~b mics~n"
              "Median: ~b mics~n"
              "Average: ~b mics~n",
              [Min, Max, Med, Avg]),
    Med.

tc_loop(_M, _F, _A, 0, List) ->
    List;
tc_loop(M, F, A, N, List) ->
    case timer:tc(M, F, A) of
        {_T, {'EXIT', Reason}} -> exit(Reason);
        {T, _Result} -> tc_loop(M, F, A, N - 1, [T|List])
    end.

%%%% Private Functions

run_command(CommandList) ->
    Result = os:cmd(string:join(CommandList, " ")),
    io:format("~s~n", [Result]).

dbgc(MFA)    -> dbg:ctp(MFA).
dbge(MFA, O) -> dbg:tracer(), dbg:p(all, call), dbg:tp(MFA, O).
dbgl(MFA, O) -> dbg:tracer(), dbg:p(all, call), dbg:tpl(MFA, O).
dbg_rt() -> x.

base_lib_path() ->
    KernAppPath = code:where_is_file("kernel.app"),
    string:substr(KernAppPath, 1, string:str(KernAppPath,"kernel") - 1).

 

2012-11-20 09:36 补充一版

 
%%
%% ----------------------------------------------------------------------------
%% "THE BEER-WARE LICENSE" (Revision 42.1):
%% <gustav.simonsson@gmail.com> wrote this file.
%% As long as you retain this notice you
%% can do whatever you want with this stuff. If we meet some day, and you think
%% this stuff is worth it, you can buy me a beer in return. 
%% ----------------------------------------------------------------------------
%%
%%%-------------------------------------------------------------------
%%% @author Gustav Simonsson <gustav.simonsson@gmail.com>
%%% @doc
%%%
%%% Miscellaneous Erlang function collection.
%%%
%%% @end
%%% Created : 29 Nov 2011 by Gustav Simonsson <gustav.simonsson@gmail.com>
%%%-------------------------------------------------------------------
-module(gs_util).

-compile(export_all).

words(Words) ->
    lists:flatten([0|| _X <- lists:seq(1, Words div 2)]).

substrings(S) -> 
    Slen = length(S),
    [string:sub_string(S,B,E) || 
        B <- lists:seq(1, Slen), E <- lists:seq(B, Slen)].

get_file_lines(F) ->
    get_file_lines_acc(F, []).
get_file_lines_acc(F, Acc) ->
    case file:read_line(F) of
        eof ->
            Acc;
        {ok, Data} ->
            get_file_lines_acc(F, [Data | Acc])
    end.

p(S, S2) ->
    io:format("~n~p:~n~p~n", [S, S2]).

int_to_month(Int) ->
    lists:nth(Int, [jan, feb, mar, apr, may, jun, jul, aug,
                    sep, oct, nov, dec]).

fat_processes() ->
    fat_processes(10).
fat_processes(C) ->
    L = lists:sort([{proplists:get_value(heap_size,L),
                     P,
                     proplists:get_value(initial_call, L),
                     proplists:get_value(current_function, L)}
                    ||{L,P} <- [{process_info(P), P} || P <- processes()]]),
    lists:reverse(lists:nthtail(length(L) - C, L)).

t(Mod, Fun, Args) ->
    dbg:stop_clear(),
    dbg:start(),
    dbg:tracer(),
    dbg:p(all,c),
    dbg:tpl(Mod, Fun, Args).

intervals(Start, Stop, _) when Start > Stop ->
    [];
intervals(Start, Stop, N) when Start == Stop; (Start + N) > Stop ->
    [{Start, Stop}];
intervals(Start, Stop, N) ->
    [{Start, Start + N} | intervals(Start + N + 1, Stop, N)].

 

2012-11-23 09:49

-module(user_default).

-export([sync/0]).
-export([make/0]).
-export([git/1]).
-export([reload/0]).
-export([reload_then/1]).

-export([dbg/0]).
-export([dbg/1]).
-export([dbg/2]).
-export([dbg/3]).
-export([dbg/4]).

-export([tc_avg/4]).

-compile(inline).

%% Reload code
reload() ->
    LibExclude = base_lib_path(),
    Modules = [M || {M, P} <- code:all_loaded(), is_list(P) andalso string:str(P, LibExclude) =:= 0],
    [shell_default:l(M) || M <- Modules].

%% Reload code then exec F
reload_then(F) ->
    reload(),
    F().

%% Compiles all files in Emakefile and load into current shell.
sync() ->
    make:all([load]).

%% Run the make command in shell.
make() ->
    run_command(["make", "all"]).

%% Run git command in shell.
git(Command) ->
    CommandList = ["git", Command],
    run_command(CommandList).

dbg()                           -> dbg:tracer().

dbg(c)                          -> dbg:stop_clear();
dbg(M)                          -> dbge({M, '_', '_'}, []).

dbg(M, c)                       -> dbgc({M, '_', '_'});
dbg(M, r)                       -> dbge({M, '_', '_'}, dbg_rt());
dbg(M, l)                       -> dbgl({M, '_', '_'}, []);
dbg(M, lr)                      -> dbgl({M, '_', '_'}, dbg_rt());
dbg(M, F) when is_atom(F)       -> dbge({M,   F, '_'}, []);
dbg(M, O)                       -> dbge({M, '_', '_'}, O).

dbg(M, F, c)                    -> dbgc({M,   F, '_'});
dbg(M, F, l)                    -> dbgl({M,   F, '_'}, dbg_rt());
dbg(M, F, r)                    -> dbge({M,   F, '_'}, dbg_rt());
dbg(M, F, lr)                   -> dbgl({M,   F, '_'}, dbg_rt());
dbg(M, F, A) when is_integer(A) -> dbge({M,   F,   A}, []);
dbg(M, F, O)                    -> dbge({M,   F, '_'}, O).

dbg(M, F, A, c)                 -> dbgc({M,   F,   A});
dbg(M, F, A, r)                 -> dbge({M,   F,   A}, dbg_rt());
dbg(M, F, A, l)                 -> dbgl({M,   F,   A}, dbg_rt());
dbg(M, F, A, lr)                -> dbgl({M,   F,   A}, dbg_rt());
dbg(M, F, A, O)                 -> dbge({M,   F,   A}, O).

tc_avg(M, F, A, N) when N > 1 ->
    L = tl(lists:reverse(tc_loop(M, F, A, N, []))),
    Length = length(L),
    Min = lists:min(L),
    Max = lists:max(L),
    Med = lists:nth(round((Length / 2)), lists:sort(L)),
    Avg = round(lists:foldl(fun(X, Sum) -> X + Sum end, 0, L) / Length),
    io:format("Range: ~b - ~b mics~n"
              "Median: ~b mics~n"
              "Average: ~b mics~n",
              [Min, Max, Med, Avg]),
    Med.

tc_loop(_M, _F, _A, 0, List) ->
    List;
tc_loop(M, F, A, N, List) ->
    case timer:tc(M, F, A) of
        {_T, {'EXIT', Reason}} -> exit(Reason);
        {T, _Result} -> tc_loop(M, F, A, N - 1, [T|List])
    end.

%%%% Private Functions

run_command(CommandList) ->
    Result = os:cmd(string:join(CommandList, " ")),
    io:format("~s~n", [Result]).

dbgc(MFA)    -> dbg:ctp(MFA).
dbge(MFA, O) -> dbg:tracer(), dbg:p(all, call), dbg:tp(MFA, O).
dbgl(MFA, O) -> dbg:tracer(), dbg:p(all, call), dbg:tpl(MFA, O).
dbg_rt() -> x.

base_lib_path() ->
    KernAppPath = code:where_is_file("kernel.app"),
    string:substr(KernAppPath, 1, string:str(KernAppPath,"kernel") - 1).

 

 

 

 是不是省了好多麻烦?打开Shell试一下吧
 
 
最后一张小图

 
 晚安!