You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: documentation2/B08-Macro.md
+118Lines changed: 118 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -106,3 +106,121 @@ cargo run
106
106
```bash
107
107
I am learning Rust!
108
108
```
109
+
110
+
Here, we create a macro called `print_message` which takes an argument `$message`. The argument(s) of a macro are prefixed by a dollar sign `$` and type annotated with a **designator**.
111
+
112
+
Rust will try to match the patterns defined within the match rules. In the above example our rule is:
113
+
114
+
```rust
115
+
($message:expr) => {
116
+
println!("{}", $message)
117
+
};
118
+
```
119
+
120
+
The first part after the dollar sign `$` is the name of the variable. We capture it as a `$message`.
121
+
122
+
The part after the semicolon `:` is called a designator, which are types that we can choose to match for. We are using the expression designator (`expr`) in the example.
123
+
124
+
Now, when we call the macro `print_message!("I am learning Rust!")` it matches our input expression and captures the `$message` variable.
125
+
126
+
Here, `$message` is assigned to `"I am learning Rust!"` which is then passed into `println!("{}", $message)`.
127
+
128
+
It will generate code that is equivalent to writing `println!("{}", "I am learning Rust!")`. The `$message` argument allows us to specify the message to print.
129
+
130
+
____
131
+
132
+
#### Note:
133
+
134
+
There are many designators that we can use inside a macro rule body:
135
+
136
+
-`stmt`: a statement
137
+
138
+
-`pat`: a pattern
139
+
140
+
-`expr`: an expression
141
+
142
+
-`ty`: a type
143
+
144
+
-`ident`: an identifier
145
+
146
+
- …
147
+
148
+
____
149
+
150
+
____
151
+
152
+
## Macro Repetitions in Rust
153
+
154
+
Rust macro is also useful when we need to generate repetitive code. We can define a macro to accept arguments and repeat the generated code based on those arguments.
155
+
156
+
The `macro_rules!` macro supports repetition using the `$(...)*` syntax. The `...` inside the parentheses can be any valid Rust expression or a pattern.
157
+
158
+
Here's an example that demonstrates macro repetition:
159
+
160
+
```rust
161
+
// A macro which uses repetitions
162
+
macro_rules!repeat_print {
163
+
// match rule which matches multiple expressions in an argument
164
+
($($x:expr),*) => {
165
+
$(
166
+
println!("{}", $x);
167
+
)*
168
+
};
169
+
}
170
+
171
+
fnmain() {
172
+
// Call the macro with multiple arguments
173
+
repeat_print!(1, 2, 3);
174
+
}
175
+
```
176
+
177
+
```bash
178
+
cargo build
179
+
```
180
+
181
+
```bash
182
+
cargo run
183
+
```
184
+
185
+
### Output
186
+
187
+
```bash
188
+
1
189
+
2
190
+
3
191
+
```
192
+
193
+
Here, the macro `repeat_print` takes a single argument, `($($x:expr),*)`, which is a repeating pattern.
194
+
195
+
The pattern consists of zero or more expressions, separated by commas, that are matched by the macro. The star (`*`) symbol at the end will repeatedly match against the pattern inside `$()`.
196
+
197
+
____
198
+
199
+
200
+
#### Breakdown of macro match rule in Rust from image
201
+
202
+

203
+
204
+
```rust
205
+
( $( $x:expr ),* )
206
+
```
207
+
208
+
The asterisk * will repeat pattern inside the `$(...)`
209
+
210
+
The comma, is the separator for the match expression
211
+
212
+
____
213
+
214
+
The code inside the curly braces `println!("{}", $x);`, is repeated zero or more times, once for each expression in the list of arguments as it is wrapped around `$(...)*` in the body of the macro definition. The `$x` in the code refers to the matched expressions.
215
+
216
+
Each iteration of the generated code will print a different expression. Now, when we call `repeat_print!(1, 2, 3);` the macro will generate this code:
217
+
218
+
```bash
219
+
println!("{}", 1); // matches argument 1,
220
+
println!("{}", 2); // matches argument 2,
221
+
println!("{}", 3); // matches argument 3
222
+
```
223
+
224
+
Thus, this macro `repeat_print!` can print multiple expressions in a concise and convenient manner, without having to write out the `println!` macro every time.
0 commit comments