@@ -192,6 +192,53 @@ To keep this system simple and correct, `#[macro_use] extern crate ...` may
192
192
only appear at the root of your crate, not inside ` mod ` . This ensures that
193
193
` $crate ` is a single identifier.
194
194
195
+ # The deep end
196
+
197
+ The introductory chapter mentioned recursive macros, but it did not give the
198
+ full story. Recursive macros are useful for another reason: Each recursive
199
+ invocation gives you another opportunity to pattern-match the macro's
200
+ arguments.
201
+
202
+ As an extreme example, it is possible, though hardly advisable, to implement
203
+ the [ Bitwise Cyclic Tag] ( http://esolangs.org/wiki/Bitwise_Cyclic_Tag ) automaton
204
+ within Rust's macro system.
205
+
206
+ ``` rust
207
+ #![feature(trace_macros)]
208
+
209
+ macro_rules! bct {
210
+ // cmd 0: d ... => ...
211
+ (0 , $ ($ ps : tt ),* ; $ _d : tt )
212
+ => (bct! ($ ($ ps ),* , 0 ; ));
213
+ (0 , $ ($ ps : tt ),* ; $ _d : tt , $ ($ ds : tt ),* )
214
+ => (bct! ($ ($ ps ),* , 0 ; $ ($ ds ),* ));
215
+
216
+ // cmd 1p: 1 ... => 1 ... p
217
+ (1 , $ p : tt , $ ($ ps : tt ),* ; 1 )
218
+ => (bct! ($ ($ ps ),* , 1 , $ p ; 1 , $ p ));
219
+ (1 , $ p : tt , $ ($ ps : tt ),* ; 1 , $ ($ ds : tt ),* )
220
+ => (bct! ($ ($ ps ),* , 1 , $ p ; 1 , $ ($ ds ),* , $ p ));
221
+
222
+ // cmd 1p: 0 ... => 0 ...
223
+ (1 , $ p : tt , $ ($ ps : tt ),* ; $ ($ ds : tt ),* )
224
+ => (bct! ($ ($ ps ),* , 1 , $ p ; $ ($ ds ),* ));
225
+
226
+ // halt on empty data string
227
+ ( $ ($ ps : tt ),* ; )
228
+ => (());
229
+ }
230
+
231
+ fn main () {
232
+ trace_macros! (true );
233
+ # /* just check the definition
234
+ bct!(0, 0, 1, 1, 1 ; 1, 0, 1);
235
+ # */
236
+ }
237
+ ```
238
+
239
+ Exercise: use macros to reduce duplication in the above definition of the
240
+ ` bct! ` macro.
241
+
195
242
# A final note
196
243
197
244
Macros, as currently implemented, are not for the faint of heart. Even
0 commit comments