-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathappendix-04-macros.html
More file actions
605 lines (537 loc) · 43.4 KB
/
Copy pathappendix-04-macros.html
File metadata and controls
605 lines (537 loc) · 43.4 KB
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
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>D - Macros - D - Macros - The Rust Programming Language</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<base href="">
<link rel="stylesheet" href="book.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">
<link rel="shortcut icon" href="favicon.png">
<!-- Font Awesome -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme -->
<style>
.page-wrapper.has-warning > .nav-chapters {
/* add height for warning content & margin */
top: 120px;
}
p.warning {
background-color: rgb(242, 222, 222);
border-bottom-color: rgb(238, 211, 215);
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-bottom-style: solid;
border-bottom-width: 0.666667px;
border-image-outset: 0 0 0 0;
border-image-repeat: stretch stretch;
border-image-slice: 100% 100% 100% 100%;
border-image-source: none;
border-image-width: 1 1 1 1;
border-left-color: rgb(238, 211, 215);
border-left-style: solid;
border-left-width: 0.666667px;
border-right-color: rgb(238, 211, 215);
border-right-style: solid;
border-right-width: 0.666667px;
border-top-color: rgb(238, 211, 215);
border-top-left-radius: 4px;
border-top-right-radius: 4px;
border-top-style: solid;
border-top-width: 0.666667px;
color: rgb(185, 74, 72);
margin-bottom: 0px;
margin-left: 0px;
margin-right: 0px;
margin-top: 30px;
padding-bottom: 8px;
padding-left: 14px;
padding-right: 35px;
padding-top: 8px;
}
p.warning strong {
color: rgb(185, 74, 72)
}
p.warning a {
color: rgb(0, 136, 204)
}
a .hljs {
color: #4183c4;
}
.rust .content a .hljs,
.coal .content a .hljs,
.navy .content a .hljs {
color: #2b79a2;
}
a:hover .hljs {
text-decoration: underline;
}
/* Styles keystrokes such as ctrl-C */
.keystroke {
font-variant: small-caps;
}
</style>
<!-- Fetch Clipboard.js from CDN but have a local fallback -->
<script src="https://cdn.jsdelivr.net/clipboard.js/1.6.1/clipboard.min.js"></script>
<script>
if (typeof Clipboard == 'undefined') {
document.write(unescape("%3Cscript src='clipboard.min.js'%3E%3C/script%3E"));
}
</script>
<!-- Fetch JQuery from CDN but have a local fallback -->
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script>
if (typeof jQuery == 'undefined') {
document.write(unescape("%3Cscript src='jquery.js'%3E%3C/script%3E"));
}
</script>
<!-- Fetch store.js from local - TODO add CDN when 2.x.x is available on cdnjs -->
<script src="store.js"></script>
<!-- Custom JS script -->
</head>
<body class="light">
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme = store.get('mdbook-theme');
if (theme === null || theme === undefined) { theme = 'light'; }
$('body').removeClass().addClass(theme);
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var sidebar = store.get('mdbook-sidebar');
if (sidebar === "hidden") { $("html").addClass("sidebar-hidden") }
else if (sidebar === "visible") { $("html").addClass("sidebar-visible") }
</script>
<div id="sidebar" class="sidebar">
<ul class="chapter"><li><a href="ch01-00-introduction.html"><strong>1.</strong> Introduction</a></li><li><ul class="section"><li><a href="ch01-01-installation.html"><strong>1.1.</strong> Installation</a></li><li><a href="ch01-02-hello-world.html"><strong>1.2.</strong> Hello, World!</a></li></ul></li><li><a href="ch02-00-guessing-game-tutorial.html"><strong>2.</strong> Guessing Game Tutorial</a></li><li><a href="ch03-00-common-programming-concepts.html"><strong>3.</strong> Common Programming Concepts</a></li><li><ul class="section"><li><a href="ch03-01-variables-and-mutability.html"><strong>3.1.</strong> Variables and Mutability</a></li><li><a href="ch03-02-data-types.html"><strong>3.2.</strong> Data Types</a></li><li><a href="ch03-03-how-functions-work.html"><strong>3.3.</strong> How Functions Work</a></li><li><a href="ch03-04-comments.html"><strong>3.4.</strong> Comments</a></li><li><a href="ch03-05-control-flow.html"><strong>3.5.</strong> Control Flow</a></li></ul></li><li><a href="ch04-00-understanding-ownership.html"><strong>4.</strong> Understanding Ownership</a></li><li><ul class="section"><li><a href="ch04-01-what-is-ownership.html"><strong>4.1.</strong> What is Ownership?</a></li><li><a href="ch04-02-references-and-borrowing.html"><strong>4.2.</strong> References & Borrowing</a></li><li><a href="ch04-03-slices.html"><strong>4.3.</strong> Slices</a></li></ul></li><li><a href="ch05-00-structs.html"><strong>5.</strong> Using Structs to Structure Related Data</a></li><li><ul class="section"><li><a href="ch05-01-defining-structs.html"><strong>5.1.</strong> Defining and Instantiating Structs</a></li><li><a href="ch05-02-example-structs.html"><strong>5.2.</strong> An Example Program Using Structs</a></li><li><a href="ch05-03-method-syntax.html"><strong>5.3.</strong> Method Syntax</a></li></ul></li><li><a href="ch06-00-enums.html"><strong>6.</strong> Enums and Pattern Matching</a></li><li><ul class="section"><li><a href="ch06-01-defining-an-enum.html"><strong>6.1.</strong> Defining an Enum</a></li><li><a href="ch06-02-match.html"><strong>6.2.</strong> The <code>match</code> Control Flow Operator</a></li><li><a href="ch06-03-if-let.html"><strong>6.3.</strong> Concise Control Flow with <code>if let</code></a></li></ul></li><li><a href="ch07-00-modules.html"><strong>7.</strong> Modules</a></li><li><ul class="section"><li><a href="ch07-01-mod-and-the-filesystem.html"><strong>7.1.</strong> <code>mod</code> and the Filesystem</a></li><li><a href="ch07-02-controlling-visibility-with-pub.html"><strong>7.2.</strong> Controlling Visibility with <code>pub</code></a></li><li><a href="ch07-03-importing-names-with-use.html"><strong>7.3.</strong> Referring to Names in Different Modules</a></li></ul></li><li><a href="ch08-00-common-collections.html"><strong>8.</strong> Common Collections</a></li><li><ul class="section"><li><a href="ch08-01-vectors.html"><strong>8.1.</strong> Vectors</a></li><li><a href="ch08-02-strings.html"><strong>8.2.</strong> Strings</a></li><li><a href="ch08-03-hash-maps.html"><strong>8.3.</strong> Hash Maps</a></li></ul></li><li><a href="ch09-00-error-handling.html"><strong>9.</strong> Error Handling</a></li><li><ul class="section"><li><a href="ch09-01-unrecoverable-errors-with-panic.html"><strong>9.1.</strong> Unrecoverable Errors with <code>panic!</code></a></li><li><a href="ch09-02-recoverable-errors-with-result.html"><strong>9.2.</strong> Recoverable Errors with <code>Result</code></a></li><li><a href="ch09-03-to-panic-or-not-to-panic.html"><strong>9.3.</strong> To <code>panic!</code> or Not To <code>panic!</code></a></li></ul></li><li><a href="ch10-00-generics.html"><strong>10.</strong> Generic Types, Traits, and Lifetimes</a></li><li><ul class="section"><li><a href="ch10-01-syntax.html"><strong>10.1.</strong> Generic Data Types</a></li><li><a href="ch10-02-traits.html"><strong>10.2.</strong> Traits: Defining Shared Behavior</a></li><li><a href="ch10-03-lifetime-syntax.html"><strong>10.3.</strong> Validating References with Lifetimes</a></li></ul></li><li><a href="ch11-00-testing.html"><strong>11.</strong> Testing</a></li><li><ul class="section"><li><a href="ch11-01-writing-tests.html"><strong>11.1.</strong> Writing tests</a></li><li><a href="ch11-02-running-tests.html"><strong>11.2.</strong> Running tests</a></li><li><a href="ch11-03-test-organization.html"><strong>11.3.</strong> Test Organization</a></li></ul></li><li><a href="ch12-00-an-io-project.html"><strong>12.</strong> An I/O Project: Building a Command Line Program</a></li><li><ul class="section"><li><a href="ch12-01-accepting-command-line-arguments.html"><strong>12.1.</strong> Accepting Command Line Arguments</a></li><li><a href="ch12-02-reading-a-file.html"><strong>12.2.</strong> Reading a File</a></li><li><a href="ch12-03-improving-error-handling-and-modularity.html"><strong>12.3.</strong> Refactoring to Improve Modularity and Error Handling</a></li><li><a href="ch12-04-testing-the-librarys-functionality.html"><strong>12.4.</strong> Developing the Library’s Functionality with Test Driven Development</a></li><li><a href="ch12-05-working-with-environment-variables.html"><strong>12.5.</strong> Working with Environment Variables</a></li><li><a href="ch12-06-writing-to-stderr-instead-of-stdout.html"><strong>12.6.</strong> Writing Error Messages to Standard Error Instead of Standard Output</a></li></ul></li><li><a href="ch13-00-functional-features.html"><strong>13.</strong> Functional Language Features: Iterators and Closures</a></li><li><ul class="section"><li><a href="ch13-01-closures.html"><strong>13.1.</strong> Closures: Anonymous Functions that Can Capture Their Environment</a></li><li><a href="ch13-02-iterators.html"><strong>13.2.</strong> Processing a Series of Items with Iterators</a></li><li><a href="ch13-03-improving-our-io-project.html"><strong>13.3.</strong> Improving Our I/O Project</a></li><li><a href="ch13-04-performance.html"><strong>13.4.</strong> Comparing Performance: Loops vs. Iterators</a></li></ul></li><li><a href="ch14-00-more-about-cargo.html"><strong>14.</strong> More about Cargo and Crates.io</a></li><li><ul class="section"><li><a href="ch14-01-release-profiles.html"><strong>14.1.</strong> Customizing Builds with Release Profiles</a></li><li><a href="ch14-02-publishing-to-crates-io.html"><strong>14.2.</strong> Publishing a Crate to Crates.io</a></li><li><a href="ch14-03-cargo-workspaces.html"><strong>14.3.</strong> Cargo Workspaces</a></li><li><a href="ch14-04-installing-binaries.html"><strong>14.4.</strong> Installing Binaries from Crates.io with <code>cargo install</code></a></li><li><a href="ch14-05-extending-cargo.html"><strong>14.5.</strong> Extending Cargo with Custom Commands</a></li></ul></li><li><a href="ch15-00-smart-pointers.html"><strong>15.</strong> Smart Pointers</a></li><li><ul class="section"><li><a href="ch15-01-box.html"><strong>15.1.</strong> <code>Box<T></code> Points to Data on the Heap and Has a Known Size</a></li><li><a href="ch15-02-deref.html"><strong>15.2.</strong> The <code>Deref</code> Trait Allows Access to the Data Through a Reference</a></li><li><a href="ch15-03-drop.html"><strong>15.3.</strong> The <code>Drop</code> Trait Runs Code on Cleanup</a></li><li><a href="ch15-04-rc.html"><strong>15.4.</strong> <code>Rc<T></code>, the Reference Counted Smart Pointer</a></li><li><a href="ch15-05-interior-mutability.html"><strong>15.5.</strong> <code>RefCell<T></code> and the Interior Mutability Pattern</a></li><li><a href="ch15-06-reference-cycles.html"><strong>15.6.</strong> Creating Reference Cycles and Leaking Memory is Safe</a></li></ul></li><li><a href="ch16-00-concurrency.html"><strong>16.</strong> Fearless Concurrency</a></li><li><ul class="section"><li><a href="ch16-01-threads.html"><strong>16.1.</strong> Threads</a></li><li><a href="ch16-02-message-passing.html"><strong>16.2.</strong> Message Passing</a></li><li><a href="ch16-03-shared-state.html"><strong>16.3.</strong> Shared State</a></li><li><a href="ch16-04-extensible-concurrency-sync-and-send.html"><strong>16.4.</strong> Extensible Concurrency: <code>Sync</code> and <code>Send</code></a></li></ul></li><li><a href="ch17-00-oop.html"><strong>17.</strong> Is Rust an Object-Oriented Programming Language?</a></li><li><ul class="section"><li><a href="ch17-01-what-is-oo.html"><strong>17.1.</strong> What Does Object-Oriented Mean?</a></li><li><a href="ch17-02-trait-objects.html"><strong>17.2.</strong> Trait Objects for Using Values of Different Types</a></li><li><a href="ch17-03-oo-design-patterns.html"><strong>17.3.</strong> Object-Oriented Design Pattern Implementations</a></li></ul></li><li><a href="ch18-00-patterns.html"><strong>18.</strong> Patterns Match the Structure of Values</a></li><li><ul class="section"><li><a href="ch18-01-all-the-places-for-patterns.html"><strong>18.1.</strong> All the Places Patterns May be Used</a></li><li><a href="ch18-02-refutability.html"><strong>18.2.</strong> Refutability: Whether a Pattern Might Fail to Match</a></li><li><a href="ch18-03-pattern-syntax.html"><strong>18.3.</strong> All the Pattern Syntax</a></li></ul></li><li><a href="ch19-00-advanced-features.html"><strong>19.</strong> Advanced Features</a></li><li><ul class="section"><li><a href="ch19-01-unsafe-rust.html"><strong>19.1.</strong> Unsafe Rust</a></li><li><a href="ch19-02-advanced-lifetimes.html"><strong>19.2.</strong> Advanced Lifetimes</a></li><li><a href="ch19-03-advanced-traits.html"><strong>19.3.</strong> Advanced Traits</a></li><li><a href="ch19-04-advanced-types.html"><strong>19.4.</strong> Advanced Types</a></li><li><a href="ch19-05-advanced-functions-and-closures.html"><strong>19.5.</strong> Advanced Functions & Closures</a></li></ul></li><li><a href="ch20-00-final-project-a-web-server.html"><strong>20.</strong> Final Project: Building a Multithreaded Web Server</a></li><li><ul class="section"><li><a href="ch20-01-single-threaded.html"><strong>20.1.</strong> A Single Threaded Web Server</a></li><li><a href="ch20-02-slow-requests.html"><strong>20.2.</strong> How Slow Requests Affect Throughput</a></li><li><a href="ch20-03-designing-the-interface.html"><strong>20.3.</strong> Designing the Thread Pool Interface</a></li><li><a href="ch20-04-storing-threads.html"><strong>20.4.</strong> Creating the Thread Pool and Storing Threads</a></li><li><a href="ch20-05-sending-requests-via-channels.html"><strong>20.5.</strong> Sending Requests to Threads Via Channels</a></li><li><a href="ch20-06-graceful-shutdown-and-cleanup.html"><strong>20.6.</strong> Graceful Shutdown and Cleanup</a></li></ul></li><li><a href="appendix-00.html"><strong>21.</strong> Appendix</a></li><li><ul class="section"><li><a href="appendix-01-keywords.html"><strong>21.1.</strong> A - Keywords</a></li><li><a href="appendix-02-operators.html"><strong>21.2.</strong> B - Operators and Symbols</a></li><li><a href="appendix-03-derivable-traits.html"><strong>21.3.</strong> C - Derivable Traits</a></li><li><a href="appendix-04-macros.html" class="active"><strong>21.4.</strong> D - Macros</a></li><li><a href="appendix-05-translation.html"><strong>21.5.</strong> E - Translations</a></li><li><a href="appendix-06-newest-features.html"><strong>21.6.</strong> F - Newest Features</a></li></ul></li></ul>
</div>
<div id="page-wrapper" class="page-wrapper has-warning">
<div class="page" tabindex="-1">
<header><p class="warning">You are reading a <strong>draft</strong> of the next edition of TRPL. For more, go <a href="../index.html">here</a>.</p></header>
<div id="menu-bar" class="menu-bar">
<div class="left-buttons">
<i id="sidebar-toggle" class="fa fa-bars"></i>
<i id="theme-toggle" class="fa fa-paint-brush"></i>
</div>
<h1 class="menu-title">The Rust Programming Language</h1>
<div class="right-buttons">
<a href="print.html">
<i id="print-button" class="fa fa-print" title="Print this book"></i>
</a>
</div>
</div>
<div id="content" class="content">
<a class="header" href="appendix-04-macros.html#d---macros" id="d---macros"><h1>D - Macros</h1></a>
<p>We’ve used macros, such as <code>println!</code>, throughout this book. This appendix will
explain:</p>
<ul>
<li>What macros are and how they differ from functions</li>
<li>How to define a declarative macro to do metaprogramming</li>
<li>How to define a procedural macro to create custom <code>derive</code> traits</li>
</ul>
<p>Macros are covered in an appendix because they’re still evolving. They have
changed and will change more than the rest of the language and standard library
since Rust 1.0, so this section will likely get out of date more than the rest
of this book. The code shown here will still continue to work due to Rust’s
stability guarantees, but there may be additional capabilities or easier ways
to write macros that aren’t available at the time of this publication.</p>
<a class="header" href="appendix-04-macros.html#macros-are-more-flexible-and-complex-than-functions" id="macros-are-more-flexible-and-complex-than-functions"><h2>Macros are More Flexible and Complex than Functions</h2></a>
<p>Fundamentally, macros are a way of writing code that writes other code, which
is known as <em>metaprogramming</em>. In the previous appendix, we discussed the
<code>derive</code> attribute, which generates an implementation of various traits for
you. We’ve also used the <code>println!</code> and <code>vec!</code> macros. All of these macros
<em>expand</em> to produce more code than what you’ve written in your source code.</p>
<p>Metaprogramming is useful to reduce the amount of code you have to write and
maintain, which is also one of the roles of functions. However, macros have
some additional powers that functions don’t have, as we discussed in Chapter 1.
A function signature has to declare the number and type of parameters the
function has. Macros can take a variable number of parameters: we can call
<code>println!("hello")</code> with one argument, or <code>println!("hello {}", name)</code> with two
arguments. Also, macros are expanded before the compiler interprets the meaning
of the code, so a macro can, for example, implement a trait on a given type,
whereas a function can’t because a function gets called at runtime and a trait
needs to be implemented at compile time.</p>
<p>The downside to implementing a macro rather than a function is that macro
definitions are more complex than function definitions. You’re writing Rust
code that writes Rust code, and macro definitions are generally more difficult
to read, understand, and maintain than function definitions.</p>
<p>Another difference between macros and functions is that macro definitions
aren’t namespaced within modules like function definitions are. In order to
prevent unexpected name clashes when using a crate, when bringing an external
crate into the scope of your project, you have to explicitly bring the macros
into the scope of your project as well with the <code>#[macro_use]</code> annotation. This
example would bring all the macros defined in the <code>serde</code> crate into the scope
of the current crate:</p>
<pre><code class="language-rust ignore">#[macro_use]
extern crate serde;
</code></pre>
<p>If <code>extern crate</code> also brought macros into scope by default, you wouldn’t be
allowed to use two crates that happened to define macros with the same name. In
practice this conflict doesn’t come up much, but the more crates you use, the
more likely it is.</p>
<p>One last important difference between macros and functions: macros must be
defined or brought into scope before they’re called in a file. Unlike
functions, where we can define a function at the bottom of a file yet call it
at the top, we always have to define macros before we’re able to call them.</p>
<a class="header" href="appendix-04-macros.html#declarative-macros-with-macro_rules-for-general-metaprogramming" id="declarative-macros-with-macro_rules-for-general-metaprogramming"><h2>Declarative Macros with <code>macro_rules!</code> for General Metaprogramming</h2></a>
<p>The first form of macros in Rust, and the one that’s most widely used, is
called <em>declarative macros</em>. These are also sometimes referred to as <em>macros by
example</em>, <em><code>macro_rules!</code> macros</em>, or just plain <em>macros</em>. At their core,
declarative macros allow you to write something similar to a Rust <code>match</code>
expression. As discussed in Chapter 6, <code>match</code> expressions are control
structures that take an expression, compare the resulting value of the
expression to patterns, and then choose the code specified with the matching
pattern when the program runs. Macros also have a value that is compared to
patterns that have code associated with them, but the value is the literal Rust
code passed to the macro, the patterns match the structure of that source code,
and the code associated with each pattern is the code that is generated to
replace the code passed to the macro. This all happens during compilation.</p>
<p>To define a macro, you use the <code>macro_rules!</code> construct. Let’s explore how to
use <code>macro_rules!</code> by taking a look at how the <code>vec!</code> macro is defined. Chapter
8 covered how we can use the <code>vec!</code> macro to create a new vector that holds
particular values. For example, this macro creates a new vector with three
integers inside:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
let v: Vec<u32> = vec![1, 2, 3];
#}</code></pre></pre>
<p>We can also use <code>vec!</code> to make a vector of two integers or a vector of five
string slices. Because we don’t know the number or type of values, we can’t
define a function that is able to create a new vector with the given elements
like <code>vec!</code> can.</p>
<p>Let’s take a look at a slightly simplified definition of the <code>vec!</code> macro:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
#[macro_export]
macro_rules! vec {
( $( $x:expr ),* ) => {
{
let mut temp_vec = Vec::new();
$(
temp_vec.push($x);
)*
temp_vec
}
};
}
#}</code></pre></pre>
<blockquote>
<p>Note: the actual definition of the <code>vec!</code> macro in the standard library also
has code to pre-allocate the correct amount of memory up-front. That code
is an optimization that we’ve chosen not to include here for simplicity.</p>
</blockquote>
<p>The <code>#[macro_export]</code> annotation indicates that this macro should be made
available when other crates import the crate in which we’re defining this
macro. Without this annotation, even if someone depending on this crate uses
the <code>#[macro_use]</code> annotation, this macro would not be brought into scope.</p>
<p>Macro definitions start with <code>macro_rules!</code> and the name of the macro we’re
defining without the exclamation mark, which in this case is <code>vec</code>. This is
followed by curly brackets denoting the body of the macro definition.</p>
<p>Inside the body is a structure similar to the structure of a <code>match</code>
expression. This macro definition has one arm with the pattern <code>( $( $x:expr ),* )</code>, followed by <code>=></code> and the block of code associated with this pattern. If
this pattern matches, then the block of code will be emitted. Given that this
is the only pattern in this macro, there’s only one valid way to match; any
other will be an error. More complex macros will have more than one arm.</p>
<p>The pattern syntax valid in macro definitions is different than the pattern
syntax covered in Chapter 18 because the patterns are for matching against Rust
code structure rather than values. Let’s walk through what the pieces of the
pattern used here mean; for the full macro pattern syntax, see <a href="../../reference/macros.html">the reference</a>.</p>
<p>The <code>$x:expr</code> part of the pattern matches any Rust expression and gives the
expression the name <code>$x</code>. The <code>*</code> specifies that the pattern matches zero or
more of whatever precedes the <code>*</code>. In this case, <code>*</code> is preceded by <code>$(),</code> so
this pattern matches zero or more of whatever is inside the parentheses,
delimited by a comma. When we call this macro with <code>vec![1, 2, 3];</code>, the
pattern matches the three expressions <code>1</code>, <code>2</code>, and <code>3</code>.</p>
<p>In the body of the code associated with this arm, the <code>$()*</code> part is generated
for each part that matches <code>$()</code> in the pattern, zero or more times depending
on how many times the pattern matches. The <code>$x</code> in the code associated with the
arm is replaced with each expression matched. When we call this macro with
<code>vec![1, 2, 3];</code>, the code generated that replaces this macro call will be:</p>
<pre><code class="language-rust ignore">let mut temp_vec = Vec::new();
temp_vec.push(1);
temp_vec.push(2);
temp_vec.push(3);
temp_vec
</code></pre>
<p>We’ve defined a macro that can take any number of arguments of any type and can
generate code to create a vector containing the specified elements.</p>
<p>Given that most Rust programmers will <em>use</em> macros more than <em>write</em> macros,
that’s all we’ll discuss about <code>macro_rules!</code> in this book. To learn more about
how to write macros, consult the online documentation or other resources such
as <a href="https://danielkeep.github.io/tlborm/book/index.html">The Little Book of Rust Macros</a>.</p>
<a class="header" href="appendix-04-macros.html#procedural-macros-for-custom-derive" id="procedural-macros-for-custom-derive"><h2>Procedural Macros for Custom <code>derive</code></h2></a>
<p>The second form of macros is called <em>procedural macros</em> because they’re more
like functions (which are a type of procedure). Procedural macros accept some
Rust code as an input, operate on that code, and produce some Rust code as an
output, rather than matching against patterns and replacing the code with other
code as declarative macros do. Today, the only thing you can define procedural
macros for is to allow your traits to be implemented on a type by specifying
the trait name in a <code>derive</code> annotation.</p>
<p>Let’s create a crate named <code>hello-world</code> that defines a trait named
<code>HelloWorld</code> with one associated function named <code>hello_world</code>. Rather than
making users of our crate implement the <code>HelloWorld</code> trait for each of their
types, we’d like users to be able to annotate their type with
<code>#[derive(HelloWorld)]</code> to get a default implementation of the <code>hello_world</code>
function associated with their type. The default implementation will print
<code>Hello world, my name is TypeName!</code> where <code>TypeName</code> is the name of the type on
which this trait has been defined.</p>
<p>In other words, we’re going to write a crate that enables another programmer to
write code that looks like Listing A4-1 using our crate:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><code class="language-rust ignore">extern crate hello_world;
#[macro_use]
extern crate hello_world_derive;
use hello_world::HelloWorld;
#[derive(HelloWorld)]
struct Pancakes;
fn main() {
Pancakes::hello_world();
}
</code></pre>
<p><span class="caption">Listing A4-1: The code a user of our crate will be able
to write when we’ve written the procedural macro</span></p>
<p>This code will print <code>Hello world, my name is Pancakes!</code> when we’re done. Let’s
get started!</p>
<p>Let’s make a new library crate:</p>
<pre><code class="language-text">$ cargo new hello-world
</code></pre>
<p>First, we’ll define the <code>HelloWorld</code> trait and associated function:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
pub trait HelloWorld {
fn hello_world();
}
#}</code></pre></pre>
<p>At this point, a user of our crate could implement the trait themselves to
achieve the functionality we wanted to enable, like so:</p>
<pre><code class="language-rust ignore">extern crate hello_world;
use hello_world::HelloWorld;
struct Pancakes;
impl HelloWorld for Pancakes {
fn hello_world() {
println!("Hello world, my name is Pancakes!");
}
}
fn main() {
Pancakes::hello_world();
}
</code></pre>
<p>However, they would need to write out the implementation block for each type
they wanted to be able to use with <code>hello_world</code>; we’d like to make using our
trait more convenient for other programmers by saving them this work.</p>
<p>Additionally, we can’t provide a default implementation for the <code>hello_world</code>
function that has the behavior we want of printing out the name of the type the
trait is implemented on: Rust doesn’t have reflection capabilities, so we can’t
look up the type’s name at runtime. We need a macro to generate code at compile
time.</p>
<a class="header" href="appendix-04-macros.html#defining-procedural-macros-requires-a-separate-crate" id="defining-procedural-macros-requires-a-separate-crate"><h3>Defining Procedural Macros Requires a Separate Crate</h3></a>
<p>The next step is to define the procedural macro. At the moment, procedural
macros need to be in their own crate. Eventually, this restriction may be
lifted, but for now, it’s required. As such, there’s a convention: for a crate
named <code>foo</code>, a custom derive procedural macro crate is called <code>foo-derive</code>.
Let’s start a new crate called <code>hello-world-derive</code> inside our <code>hello-world</code>
project:</p>
<pre><code class="language-text">$ cargo new hello-world-derive
</code></pre>
<p>We’ve chosen to create the procedural macro crate within the directory of our
<code>hello-world</code> crate because the two crates are tightly related: if we change
the trait definition in <code>hello-world</code>, we’ll have to change the implementation
of the procedural macro in <code>hello-world-derive</code> as well. The two crates will
need to be published separately, and programmers using these crates will need
to add both as dependencies and bring them both into scope. It’s possible to
have the <code>hello-world</code> crate use <code>hello-world-derive</code> as a dependency and
re-export the procedural macro code, but structuring the project this way makes
it possible for programmers to easily decide they only want to use
<code>hello-world</code> if they don’t want the <code>derive</code> functionality.</p>
<p>We need to declare that the <code>hello-world-derive</code> crate is a procedural macro
crate. We also need to add dependencies on the <code>syn</code> and <code>quote</code> crates to get
useful functionality for operating on Rust code. To do these two things, add
the following to the <em>Cargo.toml</em> for <code>hello-world-derive</code>:</p>
<p><span class="filename">Filename: hello-world-derive/Cargo.toml</span></p>
<pre><code class="language-toml">[lib]
proc-macro = true
[dependencies]
syn = "0.11.11"
quote = "0.3.15"
</code></pre>
<p>To start defining the procedural macro, place the code from Listing A4-2 in
<em>src/lib.rs</em> for the <code>hello-world-derive</code> crate. Note that this won’t compile
until we add a definition for the <code>impl_hello_world</code> function. We’ve split the
code into functions in this way because the code in Listing A4-2 will be the
same for almost every procedural macro crate; it’s code that makes writing a
procedural macro more convenient. What you choose to do in the place where the
<code>impl_hello_world</code> function is called will be different and depend on the
purpose of your procedural macro.</p>
<p><span class="filename">Filename: hello-world-derive/src/lib.rs</span></p>
<pre><code class="language-rust ignore">extern crate proc_macro;
extern crate syn;
#[macro_use]
extern crate quote;
use proc_macro::TokenStream;
#[proc_macro_derive(HelloWorld)]
pub fn hello_world_derive(input: TokenStream) -> TokenStream {
// Construct a string representation of the type definition
let s = input.to_string();
// Parse the string representation
let ast = syn::parse_derive_input(&s).unwrap();
// Build the impl
let gen = impl_hello_world(&ast);
// Return the generated impl
gen.parse().unwrap()
}
</code></pre>
<p><span class="caption">Listing A4-2: Code that most procedural macro crates will
need to have for processing Rust code</span></p>
<p>We have introduced three new crates: <code>proc_macro</code>, <a href="https://crates.io/crates/syn"><code>syn</code></a>, and <a href="https://crates.io/crates/quote"><code>quote</code></a>. The
<code>proc_macro</code> crate comes with Rust, so we didn’t need to add that to the
dependencies in <em>Cargo.toml</em>. The <code>proc_macro</code> crate allows us to convert Rust
code into a string containing that Rust code. The <code>syn</code> crate parses Rust code
from a string into a data structure that we can perform operations on. The
<code>quote</code> crate takes <code>syn</code> data structures and turns them back into Rust code.
These crates make it much simpler to parse any sort of Rust code we might want
to handle: writing a full parser for Rust code is no simple task.</p>
<p>The <code>hello_world_derive</code> function is the code that will get called when a user
of our library specifies the <code>#[derive(HelloWorld)]</code> annotation on a type
because we’ve annotated the <code>hello_world_derive</code> function here with
<code>proc_macro_derive</code> and specified the same name, <code>HelloWorld</code>. This name
matches our trait named <code>HelloWorld</code>; that’s the convention most procedural
macros follow.</p>
<p>The first thing this function does is convert the <code>input</code> from a <code>TokenStream</code>
to a <code>String</code> by calling <code>to_string</code>. This <code>String</code> is a string representation
of the Rust code for which we are deriving <code>HelloWorld</code>. In the example in
Listing A4-1, <code>s</code> will have the <code>String</code> value <code>struct Pancakes;</code> because
that’s the Rust code we added the <code>#[derive(HelloWorld)]</code> annotation to.</p>
<p>At the moment, the only thing you can do with a <code>TokenStream</code> is convert it to
a string. A richer API will exist in the future.</p>
<p>What we really need is to be able to parse the Rust code <code>String</code> into a data
structure that we can then interpret and perform operations on. This is where
<code>syn</code> comes to play. The <code>parse_derive_input</code> function in <code>syn</code> takes a
<code>String</code> and returns a <code>DeriveInput</code> struct representing the parsed Rust code.
Here’s the relevant parts of the <code>DeriveInput</code> struct we get from parsing the
string <code>struct Pancakes;</code>:</p>
<pre><code class="language-rust ignore">DeriveInput {
// --snip--
ident: Ident(
"Pancakes"
),
body: Struct(
Unit
)
}
</code></pre>
<p>The fields of this struct show that the Rust code we’ve parsed is a unit struct
with the <code>ident</code> (identifier, meaning the name) of <code>Pancakes</code>. There are more
fields on this struct for describing all sorts of Rust code; check the <a href="https://docs.rs/syn/0.11.11/syn/struct.DeriveInput.html"><code>syn</code>
API docs for <code>DeriveInput</code></a> for more information.</p>
<p>We haven’t defined the <code>impl_hello_world</code> function; that’s where we’ll build
the new Rust code we want to include. Before we get to that, the last part of
this <code>hello_world_derive</code> function is using the <code>quote</code> crate’s <code>parse</code>
function to turn the output of the <code>impl_hello_world</code> function back into a
<code>TokenStream</code>. The returned <code>TokenStream</code> is added to the code that users of
our crate write so that when they compile their crate, they get extra
functionality we provide.</p>
<p>You may have noticed that we’re calling <code>unwrap</code> to panic if the calls to the
<code>parse_derive_input</code> or <code>parse</code> functions fail because they’re unable to parse
the <code>TokenStream</code> or generate a <code>TokenStream</code>. Panicking on errors is necessary
in procedural macro code because <code>proc_macro_derive</code> functions must return
<code>TokenStream</code> rather than <code>Result</code> in order to conform to the procedural macro
API. We’ve chosen to keep this example simple by using <code>unwrap</code>; in production
code you should provide more specific error messages about what went wrong by
using <code>expect</code> or <code>panic!</code>.</p>
<p>Now that we have the code to turn the annotated Rust code from a <code>TokenStream</code>
into a <code>String</code> and into a <code>DeriveInput</code> instance, let’s write the code that
will generate the code implementing the <code>HelloWorld</code> trait on the annotated
type:</p>
<p><span class="filename">Filename: hello-world-derive/src/lib.rs</span></p>
<pre><code class="language-rust ignore">fn impl_hello_world(ast: &syn::DeriveInput) -> quote::Tokens {
let name = &ast.ident;
quote! {
impl HelloWorld for #name {
fn hello_world() {
println!("Hello, World! My name is {}", stringify!(#name));
}
}
}
}
</code></pre>
<p>We are able to get an <code>Ident</code> struct instance containing the name (identifier)
of the annotated type using <code>ast.ident</code>. With the code from Listing A4-1,
<code>name</code> will be <code>Ident("Pancakes")</code>.</p>
<p>The <code>quote!</code> macro from the <code>quote</code> crate lets us write up the Rust code that
we wish to return and convert it into <code>quote::Tokens</code>. The <code>quote!</code> macro lets
us use some really cool templating mechanics; we can write <code>#name</code> and <code>quote!</code>
will replace it with the value in the variable named <code>name</code>. You can even do
some repetition similar to the way regular macros work. Check out <a href="https://docs.rs/quote">the <code>quote</code>
crate’s docs</a> for a thorough introduction.</p>
<p>What we want to do for our procedural macro is generate an implementation of
our <code>HelloWorld</code> trait for the type the user of our crate has annotated, which
we can get by using <code>#name</code>. The trait implementation has one function,
<code>hello_world</code>, and the function body contains the functionality we want to
provide: printing <code>Hello, World! My name is</code> and then the name of the type the
user of our crate has annotated. The <code>stringify!</code> macro used here is built into
Rust. It takes a Rust expression, such as <code>1 + 2</code>, and at compile time turns
the expression into a string literal, such as <code>"1 + 2"</code>. This is different than
<code>format!</code> or <code>println!</code>, which evaluate the expression and then turn the result
into a <code>String</code>. There’s a possibility that <code>#name</code> would be an expression that
we would want to print out literally, and <code>stringify!</code> also saves an allocation
by converting <code>#name</code> to a string literal at compile time.</p>
<p>At this point, <code>cargo build</code> should complete successfully in both <code>hello-world</code>
and <code>hello-world-derive</code>. Let’s hook these crates up to the code in Listing
A4-1 to see it in action! Create a new binary project in your <code>projects</code>
directory with <code>cargo new --bin pancakes</code>. We need to add both <code>hello-world</code>
and <code>hello-world-derive</code> as dependencies in the <code>pancakes</code> crate’s
<em>Cargo.toml</em>. If you’ve chosen to publish your versions of <code>hello-world</code> and
<code>hello-world-derive</code> to <em>https://crates.io</em> they would be regular dependencies;
if not, you can specify them as <code>path</code> dependencies as follows:</p>
<pre><code class="language-toml">[dependencies]
hello_world = { path = "../hello-world" }
hello_world_derive = { path = "../hello-world/hello-world-derive" }
</code></pre>
<p>Put the code from Listing A4-1 into <em>src/main.rs</em>, and executing <code>cargo run</code>
should print <code>Hello, World! My name is Pancakes</code>! The implementation of the
<code>HelloWorld</code> trait from the procedural macro was included without the
<code>pancakes</code> crate needing to implement it; the <code>#[derive(HelloWorld)]</code> took care
of adding the trait implementation.</p>
<a class="header" href="appendix-04-macros.html#the-future-of-macros" id="the-future-of-macros"><h2>The Future of Macros</h2></a>
<p>In the future, we’ll be expanding both declarative and procedural macros. A
better declarative macro system will be used with the <code>macro</code> keyword, and
we’ll add more types of procedural macros, for more powerful tasks than only
<code>derive</code>. These systems are still under development at the time of publication;
please consult the online Rust documentation for the latest information.</p>
</div>
<!-- Mobile navigation buttons -->
<a rel="prev" href="appendix-03-derivable-traits.html" class="mobile-nav-chapters previous">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="appendix-05-translation.html" class="mobile-nav-chapters next">
<i class="fa fa-angle-right"></i>
</a>
</div>
<a href="appendix-03-derivable-traits.html" class="nav-chapters previous" title="You can navigate through the chapters using the arrow keys">
<i class="fa fa-angle-left"></i>
</a>
<a href="appendix-05-translation.html" class="nav-chapters next" title="You can navigate through the chapters using the arrow keys">
<i class="fa fa-angle-right"></i>
</a>
</div>
<!-- Local fallback for Font Awesome -->
<script>
if ($(".fa").css("font-family") !== "FontAwesome") {
$('<link rel="stylesheet" type="text/css" href="_FontAwesome/css/font-awesome.css">').prependTo('head');
}
</script>
<!-- Livereload script (if served using the cli tool) -->
<script src="highlight.js"></script>
<script src="book.js"></script>
</body>
</html>