2007/05/04

Erlang のマクロ

Erlang のマクロは C のマクロに似ています。
-define で定義し使用するときは ? を付けます。
モジュール名やファイル名を表す定義済マクロがあります。
定義時にマクロに引数に ?? を付けるとその引数をそのまま文字列として展開します。EUnit で便利に使われています。
-ifdef, -ifndef, -else, -endif で条件付きコンパイルができます。


-module(macro_sample).
-compile(export_all).

-define(MacroValue, "Not Debug!").
-define(MacroPreDef, io:format("MODULE: ~p, MODULE_STRING: ~p, FILE: ~p, LINE: ~p, MACHINE: ~p~n", [?MODULE, ?MODULE_STRING, ?FILE, ?LINE, ?MACHINE])).

-ifdef(debug).
-undef(MacroValue).
-define(MacroValue, "Debug Mode!").
-define(LOG(X), io:format("{~p,~p}: ~s = ~p~n", [?MODULE,?LINE,??X,X])).
-else.
-define(LOG(X), ok).
-endif.

-ifndef(debug).
-define(MM, not_debug).
-else.
-define(MM, debug).
-endif.

main() ->
io:format("~p, ~p~n", [?MacroValue, ?MM]),
?MacroPreDef,
?LOG(1 + 2),
?LOG(begin {H, M, S} = time(), lists:flatten(io_lib:format("~p:~p:~p", [H, M, S])) end).

普通にコンパイルした場合

(emacs@localhost)83> c("/home/ancient/letter/erlang/junk/macro_sample", [{outdir, "/home/ancient/letter/erlang/junk/"}]).
{ok,macro_sample}
(emacs@localhost)84> macro_sample:main().
"Not Debug!", not_debug
MODULE: macro_sample, MODULE_STRING: "macro_sample", FILE: "/home/ancient/letter/erlang/junk/macro_sample.erl", LINE: 24, MACHINE: 'BEAM'
ok

{d, debug} として debug を定義してコンパイルした場合

(emacs@localhost)85> c("/home/ancient/letter/erlang/junk/macro_sample", [{outdir, "/home/ancient/letter/erlang/junk/"}, {d, debug}]).
{ok,macro_sample}
(emacs@localhost)86> macro_sample:main().
"Debug Mode!", debug
MODULE: macro_sample, MODULE_STRING: "macro_sample", FILE: "/home/ancient/letter/erlang/junk/macro_sample.erl", LINE: 24, MACHINE: 'BEAM'
{macro_sample,25}: 1 + 2 = 3
{macro_sample,26}: begin { H , M , S } = time ( ) , lists : flatten ( io_lib : format ( "~p:~p:~p" , [ H , M , S ] ) ) end = "5:22:54"
ok


コンパイル時に P オプションを付けるとマクロ展開後のファイルが作成されます。

(emacs@localhost)87> c("/home/ancient/letter/erlang/junk/macro_sample", [{outdir, "/home/ancient/letter/erlang/junk/"}, {d, debug}, 'P']).
** Warning: No object file created - nothing loaded **
ok

マクロ展開後のファイル

-file("/home/ancient/letter/erlang/junk/macro_sample.erl", 1).

-module(macro_sample).

-compile(export_all).

main() ->
io:format("~p, ~p~n", ["Debug Mode!",debug]),
io:format("MODULE: ~p, MODULE_STRING: ~p, FILE: ~p, LINE: ~p, MACHI"
"NE: ~p~n",
[macro_sample,
"macro_sample",
"/home/ancient/letter/erlang/junk/macro_sample.erl",
24,
'BEAM']),
io:format("{~p,~p}: ~s = ~p~n", [macro_sample,25,"1 + 2",1 + 2]),
io:format("{~p,~p}: ~s = ~p~n",
[macro_sample,
26,
"begin { H , M , S } = time ( ) , lists : flatten ( io_l"
"ib : format ( \"~p:~p:~p\" , [ H , M , S ] ) ) end",
begin
{H,M,S} = time(),
lists:flatten(io_lib:format("~p:~p:~p", [H,M,S]))
end]).

0 件のコメント: