aboutsummaryrefslogtreecommitdiffstats
path: root/system/doc/extensions/macros.xml
blob: feb3de61026d6ba2b4cd50a60bb34447ae941a6e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
<?xml version="1.0" encoding="latin1" ?>
<!DOCTYPE chapter SYSTEM "chapter.dtd">

<chapter>
  <header>
    <copyright>
      <year>1997</year><year>2009</year>
      <holder>Ericsson AB. All Rights Reserved.</holder>
    </copyright>
    <legalnotice>
      The contents of this file are subject to the Erlang Public License,
      Version 1.1, (the "License"); you may not use this file except in
      compliance with the License. You should have received a copy of the
      Erlang Public License along with this software. If not, it can be
      retrieved online at http://www.erlang.org/.
    
      Software distributed under the License is distributed on an "AS IS"
      basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
      the License for the specific language governing rights and limitations
      under the License.
    
    </legalnotice>

    <title>Macros</title>
    <prepared>Joe Armstrong</prepared>
    <responsible>Bjarne D&auml;cker</responsible>
    <docno>1</docno>
    <approved>Bjarne D&auml;Ker</approved>
    <checked></checked>
    <date>96-09-10</date>
    <rev>PA1</rev>
    <file>macros.sgml</file>
  </header>
  <p>Macros in Erlang are written with the following syntax:</p>
  <code type="none">

-define(Const, Replacement).
-define(Fun(Var1, Var2,.., Var), Replacement).  </code>
  <p>Macros are expanded when the syntax <c>?MacroName</c> is encountered.</p>
  <p>Consider the macro definition:</p>
  <code type="none">

-define(timeout, 200).  </code>
  <p>The expression <c>?timeout</c>, which can occur anywhere in the code which follows the macro definition, will be replaced by <c>200</c>.</p>
  <p>Macros with arguments are written as follows:</p>
  <code type="none">

      -define(macro1(X, Y), {a, X, b, Y}).  </code>
  <p>This type of macro can be used as follows:</p>
  <code type="none">

bar(X) ->
    ?macro1(a, b),
    ?macro1(X, 123)  </code>
  <p>This expands to:</p>
  <code type="none">

bar(X) ->
    {a,a,b,b},
    {a,X,b,123}.  </code>

  <section>
    <title>Macros and Tokens</title>
    <p>Macro expansion works at a token level. We might define a macro as follows:</p>
    <code type="none">

-define(macro2(X, Y), {a,X,b,Y).    </code>
    <p>The replacement value of the macro is not a valid Erlang term because the closing right curly bracket is missing. <c>macro2</c> expands into a sequence of tokens <c>{</c>, <c>a</c>, <c>X</c>  which are then pasted into the place where the macro is used.</p>
    <p>We might use this macro as follows:</p>
    <code type="none">

bar() ->
    ?macro2(x,y)}.    </code>
    <p>This will expand into the valid sequence of tokens <c>{a,x,y,b}</c> before being parsed and compiled.</p>
    <note>
      <p>It is good programming practise to ensure that the replacement text of a macro is a valid Erlang syntactic form.</p>
    </note>
  </section>

  <section>
    <title>Pre-Defined Macros</title>
    <p>The following macros are pre-defined:</p>
    <taglist>
      <tag><c>?MODULE</c>. </tag>
      <item>This macro returns the name of the current module.
      </item>
      <tag><c>?MODULE_STRING</c>. </tag>
      <item>This macro returns the name of the current module, as a string.</item>
      <tag><c>?FILE</c>.</tag>
      <item>This macro returns the current file name.</item>
      <tag><c>?LINE</c>.</tag>
      <item>This macro returns the current line number.</item>
      <tag><c>?MACHINE</c>.</tag>
      <item>This macro returns the current machine name,
      <c>'BEAM'</c>,</item>
    </taglist>
  </section>

  <section>
    <title>Stringifying Macro Arguments</title>
    <p>The construction <c>??Arg</c> for an argument to a macro expands to a
      string containing the tokens of the argument, similar to the
      <c>#arg</c> stringifying construction in C. This was added in Erlang
      5.0 (OTP R7A).</p>
    <p>Example:</p>
    <code type="none">
-define(TESTCALL(Call), io:format("Call ~s: ~w~n", [??Call, Call])).

?TESTCALL(myfunction(1,2)),
?TESTCALL(you:function(2,1)).</code>
    <p>results in</p>
    <code type="none">
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)]).</code>
  </section>

  <section>
    <title>Flow Control in Macros</title>
    <p>The following macro directives are supplied:</p>
    <taglist>
      <tag>-undef(Macro).</tag>
      <item>Causes the macro to behave as if it had never been defined.</item>
      <tag>-ifdef(Macro).</tag>
      <item>Do the following lines if <c>Macro</c> is defined.</item>
      <tag>-ifndef(Macro).</tag>
      <item>Do the following lines if <c>Macro</c> is not defined.</item>
      <tag>-else.</tag>
      <item>"else" macro</item>
      <tag>-endif.</tag>
      <item>"endif" macro.</item>
    </taglist>
    <p>The conditional macros must be properly nested. They are usually grouped as follows:</p>
    <code type="none">

-ifdef(debug)
-define(....)
-else
-define(...)
-endif    </code>
    <p>The following example illustrates this grouping:</p>
    <code type="none">

-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.    </code>
    <p>Given these definitions, the expression <c>?trace("X=", X).</c> in line 10 of the module <c>foo</c> expands to:</p>
    <code type="none">

io:format("Mod:~w line:~w ~p ~p~n",[foo,100,"X=",[X]]),    </code>
    <p>If we remove the <c>-define(debug, true).</c> line, then the same expression expands to <c>true</c>.</p>
  </section>

  <section>
    <title>A Macro Expansion Utility</title>
    <p>The following code can be used to expand a macro and display the result:</p>
    <code type="none">

-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.</code>
    <p>Alternatively, we can compile the file with the <c>'P'</c> option. <c>compile:file(File, ['P'])</c> produces a list file <c>File.P</c>, in which the result of any macro expansions can be seen.</p>
  </section>
</chapter>