> ## 4 Macros

> 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}.

> ### 4.1 Macros and Tokens

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

> ### 4.2 Pre-Defined Macros

> The following macros are pre-defined:

> `?MODULE`.
>   This macro returns the name of the current module.
> `?MODULE_STRING`.
>   This macro returns the name of the current module, as a string.
> `?FILE`.
>   This macro returns the current file name.
> `?LINE`.
>   This macro returns the current line number.
> `?MACHINE`.
>   This macro returns the current machine name, `'BEAM'`,

> ### 4.3 Stringifying Macro Arguments

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

> ### 4.4 Flow Control in Macros

> The following macro directives are supplied:

> -undef(Macro).
>   Causes the macro to behave as if it had never been defined.
> -ifdef(Macro).
>   Do the following lines if `Macro` is defined.
> -ifndef(Macro).
>   Do the following lines if `Macro` is not defined.
> -else.
>   "else" macro
> -endif.
>   "endif" macro.

> 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`.

> ### 4.5 A Macro Expansion Utility

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

Copyright © 1991-2003 Ericsson Utvecklings AB