@@ -11,7 +11,7 @@ which both pattern-match on their input and both return early in one case,
11
11
doing nothing otherwise:
12
12
13
13
~~~~
14
- # enum T { SpecialA(uint), SpecialB(uint) };
14
+ # enum T { SpecialA(uint), SpecialB(uint) }
15
15
# fn f() -> uint {
16
16
# let input_1 = SpecialA(0);
17
17
# let input_2 = SpecialA(0);
@@ -37,7 +37,8 @@ lightweight custom syntax extensions, themselves defined using the
37
37
the pattern in the above code:
38
38
39
39
~~~~
40
- # enum T { SpecialA(uint), SpecialB(uint) };
40
+ # #![feature(macro_rules)]
41
+ # enum T { SpecialA(uint), SpecialB(uint) }
41
42
# fn f() -> uint {
42
43
# let input_1 = SpecialA(0);
43
44
# let input_2 = SpecialA(0);
@@ -55,6 +56,7 @@ early_return!(input_1 SpecialA);
55
56
early_return!(input_2 SpecialB);
56
57
# return 0;
57
58
# }
59
+ # fn main() {}
58
60
~~~~
59
61
60
62
Macros are defined in pattern-matching style: in the above example, the text
@@ -155,7 +157,8 @@ separator token (a comma-separated list could be written `$(...),*`), and `+`
155
157
instead of ` * ` to mean "at least one".
156
158
157
159
~~~~
158
- # enum T { SpecialA(uint),SpecialB(uint),SpecialC(uint),SpecialD(uint)};
160
+ # #![feature(macro_rules)]
161
+ # enum T { SpecialA(uint),SpecialB(uint),SpecialC(uint),SpecialD(uint)}
159
162
# fn f() -> uint {
160
163
# let input_1 = SpecialA(0);
161
164
# let input_2 = SpecialA(0);
@@ -175,6 +178,7 @@ early_return!(input_1, [SpecialA|SpecialC|SpecialD]);
175
178
early_return!(input_2, [SpecialB]);
176
179
# return 0;
177
180
# }
181
+ # fn main() {}
178
182
~~~~
179
183
180
184
### Transcription
@@ -215,9 +219,10 @@ solves the problem.
215
219
Now consider code like the following:
216
220
217
221
~~~~
218
- # enum T1 { Good1(T2, uint), Bad1};
222
+ # #![feature(macro_rules)]
223
+ # enum T1 { Good1(T2, uint), Bad1}
219
224
# struct T2 { body: T3 }
220
- # enum T3 { Good2(uint), Bad2};
225
+ # enum T3 { Good2(uint), Bad2}
221
226
# fn f(x: T1) -> uint {
222
227
match x {
223
228
Good1(g1, val) => {
@@ -232,6 +237,7 @@ match x {
232
237
_ => return 0 // default value
233
238
}
234
239
# }
240
+ # fn main() {}
235
241
~~~~
236
242
237
243
All the complicated stuff is deeply indented, and the error-handling code is
@@ -240,6 +246,7 @@ a match, but with a syntax that suits the problem better. The following macro
240
246
can solve the problem:
241
247
242
248
~~~~
249
+ # #![feature(macro_rules)]
243
250
macro_rules! biased_match (
244
251
// special case: `let (x) = ...` is illegal, so use `let x = ...` instead
245
252
( ($e:expr) ~ ($p:pat) else $err:stmt ;
@@ -261,9 +268,9 @@ macro_rules! biased_match (
261
268
)
262
269
)
263
270
264
- # enum T1 { Good1(T2, uint), Bad1};
271
+ # enum T1 { Good1(T2, uint), Bad1}
265
272
# struct T2 { body: T3 }
266
- # enum T3 { Good2(uint), Bad2};
273
+ # enum T3 { Good2(uint), Bad2}
267
274
# fn f(x: T1) -> uint {
268
275
biased_match!((x) ~ (Good1(g1, val)) else { return 0 };
269
276
binds g1, val )
@@ -273,13 +280,16 @@ biased_match!((g1.body) ~ (Good2(result) )
273
280
// complicated stuff goes here
274
281
return result + val;
275
282
# }
283
+ # fn main() {}
276
284
~~~~
277
285
278
286
This solves the indentation problem. But if we have a lot of chained matches
279
287
like this, we might prefer to write a single macro invocation. The input
280
288
pattern we want is clear:
281
289
282
290
~~~~
291
+ # #![feature(macro_rules)]
292
+ # fn main() {}
283
293
# macro_rules! b(
284
294
( $( ($e:expr) ~ ($p:pat) else $err:stmt ; )*
285
295
binds $( $bind_res:ident ),*
@@ -301,14 +311,18 @@ process the semicolon-terminated lines, one-by-one. So, we want the following
301
311
input patterns:
302
312
303
313
~~~~
314
+ # #![feature(macro_rules)]
304
315
# macro_rules! b(
305
316
( binds $( $bind_res:ident ),* )
306
317
# => (0))
318
+ # fn main() {}
307
319
~~~~
308
320
309
321
...and:
310
322
311
323
~~~~
324
+ # #![feature(macro_rules)]
325
+ # fn main() {}
312
326
# macro_rules! b(
313
327
( ($e :expr) ~ ($p :pat) else $err :stmt ;
314
328
$( ($e_rest:expr) ~ ($p_rest:pat) else $err_rest:stmt ; )*
@@ -322,6 +336,8 @@ The resulting macro looks like this. Note that the separation into
322
336
piece of syntax (the ` let ` ) which we only want to transcribe once.
323
337
324
338
~~~~
339
+ # #![feature(macro_rules)]
340
+ # fn main() {
325
341
326
342
macro_rules! biased_match_rec (
327
343
// Handle the first layer
@@ -365,9 +381,9 @@ macro_rules! biased_match (
365
381
)
366
382
367
383
368
- # enum T1 { Good1(T2, uint), Bad1};
384
+ # enum T1 { Good1(T2, uint), Bad1}
369
385
# struct T2 { body: T3 }
370
- # enum T3 { Good2(uint), Bad2};
386
+ # enum T3 { Good2(uint), Bad2}
371
387
# fn f(x: T1) -> uint {
372
388
biased_match!(
373
389
(x) ~ (Good1(g1, val)) else { return 0 };
@@ -376,6 +392,7 @@ biased_match!(
376
392
// complicated stuff goes here
377
393
return result + val;
378
394
# }
395
+ # }
379
396
~~~~
380
397
381
398
This technique applies to many cases where transcribing a result all at once is not possible.
0 commit comments