Macros in Erlang are written with the following syntax:
-define(Const, Replacement). -define(Fun(Var1, Var2,.., Var), Replacement).
Macros are expanded when the syntax ?MacroName
is encountered.
Consider the macro definition:
-define(timeout, 200).
The expression ?timeout
, which can occur anywhere in the code which follows the macro definition, will be replaced by 200
.
Macros with arguments are written as follows:
-define(macro1(X, Y), {a, X, b, Y}).
This type of macro can be used as follows:
bar(X) -> ?macro1(a, b), ?macro1(X, 123)
This expands to:
bar(X) -> {a,a,b,b}, {a,X,b,123}.
Macro expansion works at a token level. We might define a macro as follows:
-define(macro2(X, Y), {a,X,b,Y).
The replacement value of the macro is not a valid Erlang term because the closing right curly bracket is missing. macro2
expands into a sequence of tokens {
, a
, X
which are then pasted into the place where the macro is used.
We might use this macro as follows:
bar() -> ?macro2(x,y)}.
This will expand into the valid sequence of tokens {a,x,y,b}
before being parsed and compiled.
![]() |
It is good programming practise to ensure that the replacement text of a macro is a valid Erlang syntactic form. |
The following macros are pre-defined:
?MODULE
.
?MODULE_STRING
.
?FILE
.
?LINE
.
?MACHINE
.
'BEAM'
,
The construction ??Arg
for an argument to a macro expands to a
string containing the tokens of the argument, similar to the
#arg
stringifying construction in C. This was added in Erlang
5.0 (OTP R7A).
Example:
-define(TESTCALL(Call), io:format("Call ~s: ~w~n", [??Call, Call])). ?TESTCALL(myfunction(1,2)), ?TESTCALL(you:function(2,1)).
results in
io:format("Call ~s: ~w~n",["myfunction ( 1 , 2 )",m:myfunction(1,2)]), io:format("Call ~s: ~w~n",["you : function ( 2 , 1 )",you:function(2,1)]).
The following macro directives are supplied:
Macro
is defined.
Macro
is not defined.
The conditional macros must be properly nested. They are usually grouped as follows:
-ifdef(debug) -define(....) -else -define(...) -endif
The following example illustrates this grouping:
-define(debug, true). -ifdef(debug). -define(trace(Str, X), io:format("Mod:~w line:~w ~p ~p~n", [?MODULE,?LINE, Str, X])). -else. -define(trace(X, Y), true). -endif.
Given these definitions, the expression ?trace("X=", X).
in line 10 of the module foo
expands to:
io:format("Mod:~w line:~w ~p ~p~n",[foo,100,"X=",[X]]),
If we remove the -define(debug, true).
line, then the same expression expands to true
.
The following code can be used to expand a macro and display the result:
-module(mexpand). -export([file/1]). -import(lists, [foreach/2]). file(File) -> case epp:parse_file(File ++ ".erl", [],[]) of {ok, L} -> {ok, Stream} = file:open(File ++ ".out", write), foreach(fun(X) -> io:format(Stream,"~s~n",[erl_pp:form(X)]) end, L), file:close(Stream) end.
Alternatively, we can compile the file with the 'P'
option. compile:file(File, ['P'])
produces a list file File.P
, in which the result of any macro expansions can be seen.