Skip to content

Commit 5625a84

Browse files
committed
Add example of Macro Repititions to close out Chapter
1 parent e49031e commit 5625a84

File tree

3 files changed

+127
-7
lines changed

3 files changed

+127
-7
lines changed

documentation2/B08-Macro.md

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,121 @@ cargo run
106106
```bash
107107
I am learning Rust!
108108
```
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+
fn main() {
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+
![Screenshot of Breakdown of macro match rule in Rust from Programiz tutorial](image-1.png)
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.
225+
226+
____

documentation2/image-1.png

48.3 KB
Loading
Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
// A macro named `print_message`
2-
macro_rules! print_message {
3-
// Match rule that takes an argument expression
4-
($message:expr) => {
5-
println!("{}", $message)
1+
// A macro which uses repetitions
2+
macro_rules! repeat_print {
3+
// match rule which matches multiple expressions in an argument
4+
($($x:expr),*) => {
5+
$(
6+
println!("{}", $x);
7+
)*
68
};
79
}
810

911
fn main() {
10-
// Call the macro with an argument
11-
print_message!("I am learning Rust!");
12+
// Call the macro with multiple arguments
13+
repeat_print!(1, 2, 3);
1214
}

0 commit comments

Comments
 (0)