]> git.lizzy.rs Git - rust.git/commitdiff
Add a second, more vexing section on recursive macros
authorKeegan McAllister <kmcallister@mozilla.com>
Sat, 21 Feb 2015 05:39:03 +0000 (21:39 -0800)
committerKeegan McAllister <kmcallister@mozilla.com>
Wed, 25 Feb 2015 00:28:54 +0000 (16:28 -0800)
Fixes #22423.

src/doc/trpl/advanced-macros.md

index aff365051a4eadfc67819f0e9c45487abd1b70ad..9a4cc57a1f7214205cb66984fc1a2211e71b806d 100644 (file)
@@ -192,6 +192,53 @@ To keep this system simple and correct, `#[macro_use] extern crate ...` may
 only appear at the root of your crate, not inside `mod`. This ensures that
 `$crate` is a single identifier.
 
+# The deep end
+
+The introductory chapter mentioned recursive macros, but it did not give the
+full story. Recursive macros are useful for another reason: Each recursive
+invocation gives you another opportunity to pattern-match the macro's
+arguments.
+
+As an extreme example, it is possible, though hardly advisable, to implement
+the [Bitwise Cyclic Tag](http://esolangs.org/wiki/Bitwise_Cyclic_Tag) automaton
+within Rust's macro system.
+
+```rust
+#![feature(trace_macros)]
+
+macro_rules! bct {
+    // cmd 0:  d ... => ...
+    (0, $($ps:tt),* ; $_d:tt)
+        => (bct!($($ps),*, 0 ; ));
+    (0, $($ps:tt),* ; $_d:tt, $($ds:tt),*)
+        => (bct!($($ps),*, 0 ; $($ds),*));
+
+    // cmd 1p:  1 ... => 1 ... p
+    (1, $p:tt, $($ps:tt),* ; 1)
+        => (bct!($($ps),*, 1, $p ; 1, $p));
+    (1, $p:tt, $($ps:tt),* ; 1, $($ds:tt),*)
+        => (bct!($($ps),*, 1, $p ; 1, $($ds),*, $p));
+
+    // cmd 1p:  0 ... => 0 ...
+    (1, $p:tt, $($ps:tt),* ; $($ds:tt),*)
+        => (bct!($($ps),*, 1, $p ; $($ds),*));
+
+    // halt on empty data string
+    ( $($ps:tt),* ; )
+        => (());
+}
+
+fn main() {
+    trace_macros!(true);
+# /* just check the definition
+    bct!(0, 0, 1, 1, 1 ; 1, 0, 1);
+# */
+}
+```
+
+Exercise: use macros to reduce duplication in the above definition of the
+`bct!` macro.
+
 # A final note
 
 Macros, as currently implemented, are not for the faint of heart. Even