3
3
# Introduction
4
4
5
5
Functions are the primary tool that programmers can use to build abstractions.
6
- Sometimes, however, programmers want to abstract over compile-time syntax
7
- rather than run-time values.
8
- Macros provide syntactic abstraction.
9
- For an example of how this can be useful, consider the following two code fragments,
10
- which both pattern-match on their input and both return early in one case,
11
- doing nothing otherwise:
6
+ Sometimes, however, programmers want to perform abstractions over things that are not
7
+ runtime values. Macros provide a syntactic abstraction. For an example of how this
8
+ can be useful, consider the following two code fragments, which both pattern-match
9
+ on their input and return early in one case, and do nothing otherwise:
12
10
13
11
~~~~
14
12
# enum t { special_a(uint), special_b(uint) };
@@ -27,10 +25,9 @@ match input_2 {
27
25
# }
28
26
~~~~
29
27
30
- This code could become tiresome if repeated many times.
31
- However, no function can capture its functionality to make it possible
32
- to abstract the repetition away.
33
- Rust's macro system, however, can eliminate the repetition. Macros are
28
+ This code could become tiresome if repeated many times. However, no function
29
+ can capture its functionality to make it possible to rewrite the repetition
30
+ away. Rust's macro system, however, can eliminate the repetition. Macros are
34
31
lightweight custom syntax extensions, themselves defined using the
35
32
` macro_rules! ` syntax extension. The following ` early_return ` macro captures
36
33
the pattern in the above code:
@@ -40,7 +37,7 @@ the pattern in the above code:
40
37
# fn f() -> uint {
41
38
# let input_1 = special_a(0), input_2 = special_a(0);
42
39
macro_rules! early_return(
43
- ($inp:expr $sp:ident) => ( // invoke it like `(input_5 special_e)`
40
+ ($inp:expr $sp:ident) => ( //invoke it like `(input_5 special_e)`
44
41
match $inp {
45
42
$sp(x) => { return x; }
46
43
_ => {}
@@ -96,10 +93,10 @@ that could be invoked like: `my_macro!(i->(( 2+2 )))`.
96
93
97
94
## Invocation location
98
95
99
- A macro invocation may take the place of (and therefore expand to)
100
- an expression, an item, or a statement.
101
- The Rust parser will parse the macro invocation as a "placeholder"
102
- for whichever of those three nonterminals is appropriate for the location.
96
+ A macro invocation may take the place of (and therefore expand to) either an
97
+ expression, an item, or a statement. The Rust parser will parse the macro
98
+ invocation as a "placeholder" for whichever of those three nonterminals is
99
+ appropriate for the location.
103
100
104
101
At expansion time, the output of the macro will be parsed as whichever of the
105
102
three nonterminals it stands in for. This means that a single macro might,
@@ -115,19 +112,17 @@ The right-hand side of the `=>` follows the same rules as the left-hand side,
115
112
except that a ` $ ` need only be followed by the name of the syntactic fragment
116
113
to transcribe into the macro expansion; its type need not be repeated.
117
114
118
- The right-hand side must be enclosed by delimiters, which the transcriber ignores.
119
- Therefore ` () => ((1,2,3)) ` is a macro that expands to a tuple expression,
120
- ` () => (let $x=$val) ` is a macro that expands to a statement,
121
- and ` () => (1,2,3) ` is a macro that expands to a syntax error
122
- (since the transcriber interprets the parentheses on the right-hand-size as delimiters,
123
- and ` 1,2,3 ` is not a valid Rust expression on its own).
115
+ The right-hand side must be enclosed by delimiters, which are ignored by the
116
+ transcriber (therefore ` () => ((1,2,3)) ` is a macro that expands to a tuple
117
+ expression, ` () => (let $x=$val) ` is a macro that expands to a statement, and
118
+ ` () => (1,2,3) ` is a macro that expands to a syntax error).
124
119
125
120
Except for permissibility of ` $name ` (and ` $(...)* ` , discussed below), the
126
121
right-hand side of a macro definition is ordinary Rust syntax. In particular,
127
122
macro invocations (including invocations of the macro currently being defined)
128
123
are permitted in expression, statement, and item locations. However, nothing
129
124
else about the code is examined or executed by the macro system; execution
130
- still has to wait until run-time .
125
+ still has to wait until runtime .
131
126
132
127
## Interpolation location
133
128
@@ -292,6 +287,7 @@ A macro may accept multiple different input grammars. The first one to
292
287
successfully match the actual argument to a macro invocation is the one that
293
288
"wins".
294
289
290
+
295
291
In the case of the example above, we want to write a recursive macro to
296
292
process the semicolon-terminated lines, one-by-one. So, we want the following
297
293
input patterns:
@@ -373,19 +369,19 @@ return result + val;
373
369
# }
374
370
~~~~
375
371
376
- This technique applies to many cases where transcribing a result all at once is not possible.
377
- The resulting code resembles ordinary functional programming in some respects,
378
- but has some important differences from functional programming .
372
+ This technique is applicable in many cases where transcribing a result " all
373
+ at once" is not possible. It resembles ordinary functional programming in some
374
+ respects, but it is important to recognize the differences .
379
375
380
376
The first difference is important, but also easy to forget: the transcription
381
377
(right-hand) side of a ` macro_rules! ` rule is literal syntax, which can only
382
378
be executed at run-time. If a piece of transcription syntax does not itself
383
379
appear inside another macro invocation, it will become part of the final
384
380
program. If it is inside a macro invocation (for example, the recursive
385
- invocation of ` biased_match_rec! ` ), it does have the opportunity to affect
381
+ invocation of ` biased_match_rec! ` ), it does have the opprotunity to affect
386
382
transcription, but only through the process of attempted pattern matching.
387
383
388
- The second, related, difference is that the evaluation order of macros feels
384
+ The second difference is related: the evaluation order of macros feels
389
385
"backwards" compared to ordinary programming. Given an invocation
390
386
` m1!(m2!()) ` , the expander first expands ` m1! ` , giving it as input the literal
391
387
syntax ` m2!() ` . If it transcribes its argument unchanged into an appropriate
0 commit comments