From c22af5588e348469d79fad635a7c2b515da81723 Mon Sep 17 00:00:00 2001 From: Atliac Date: Sat, 14 Mar 2026 18:01:03 +0800 Subject: [PATCH 1/3] docs(intro): improve readability and structure of the interactive guide Expand the "How to Use This Book" section in the introduction to provide clearer instructions for learners. Added subheaders for better organization and included tips for hands-on experimentation with the runnable code blocks. --- src/introduction.md | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/introduction.md b/src/introduction.md index 8ab0a97..660ae4d 100644 --- a/src/introduction.md +++ b/src/introduction.md @@ -43,14 +43,22 @@ In this tutorial, you will learn: ## How to Use This Book -It is recommended to read the "Tutorial" part in order. +This tutorial is designed to be interactive and hands-on. Here's how to get the most out of it: -This book has many runnable and editable code blocks. It is encouraged to run them by clicking the play button at the top-right of each code block. +### Reading Order -For example: +It is recommended to read the "Tutorial" section in order. While you can explore other sections, macros build on concepts progressively, and following the intended sequence will help you understand the material better. -```rust,editable -fn main() { - println!("Hello, world!"); -} -``` +### Interactive Code Blocks + +This book contains many **runnable and editable** Rust code blocks: + +- **Runnable**: Click the play button at the top-right of any code block to execute it and see the output directly. +- **Editable**: Edit the code directly in the editor, then click the play button to re-run it with your changes. + + +### Tips for Learning + +- Try modifying the examples to understand how macros work +- Use the button to verify your changes compile and behave as expected +- Don't hesitate to break things - the tutorial is designed for experimentation From d375715c05251be263d2418a7b79af124b482a06 Mon Sep 17 00:00:00 2001 From: Atliac Date: Sat, 14 Mar 2026 20:58:45 +0800 Subject: [PATCH 2/3] docs(macros-1.0): add metavariables chapter and update reference links Add a new chapter for metavariables in the Macros 1.0 section. Include a comprehensive table of metavariable types and examples. Update SUMMARY.md and reference links for better navigation. --- src/SUMMARY.md | 3 +- src/introduction.md | 2 +- src/macros_1.0/metavariables.md | 97 +++++++++++++++++++++++++++++++++ src/macros_1.0_reference.md | 3 + 4 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 src/macros_1.0/metavariables.md create mode 100644 src/macros_1.0_reference.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 2dc4cf2..7c040ee 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -5,11 +5,12 @@ # Tutorial - [Macros 1.0: macro_rules!](./macros_1.0.md) + - [Metavariables](./macros_1.0/metavariables.md) - [Macros 2.0]() - [Procedural macros](./procedural_macros.md) # Reference -- [Macros 1.0 `macro_rules!`]() +- [Macros 1.0 `macro_rules!`](./macros_1.0_reference.md) - [Macros 2.0]() - [Procedural macros]() diff --git a/src/introduction.md b/src/introduction.md index 660ae4d..278f131 100644 --- a/src/introduction.md +++ b/src/introduction.md @@ -54,7 +54,7 @@ It is recommended to read the "Tutorial" section in order. While you can explore This book contains many **runnable and editable** Rust code blocks: - **Runnable**: Click the play button at the top-right of any code block to execute it and see the output directly. -- **Editable**: Edit the code directly in the editor, then click the play button to re-run it with your changes. +- **Editable**: Edit the code directly in the editor, then click the play button to re-run the updated code with your changes. ### Tips for Learning diff --git a/src/macros_1.0/metavariables.md b/src/macros_1.0/metavariables.md new file mode 100644 index 0000000..d05d27f --- /dev/null +++ b/src/macros_1.0/metavariables.md @@ -0,0 +1,97 @@ +# Metavariables + +Without metavariables, a rule can only match literal values exactly. + +## A First Look at Metavariables + +```rust,editable +macro_rules! print{ + ($x:tt) => { println!("{}", $x); }; +} +fn main() { + print!(1); + let v="Hello, world!"; + print!(v); +} +``` + +`$x:tt` is a metavariable named `x` with the type `tt` (token tree). + +> [!NOTE] +> You may find that other resources use the term "fragment specifier" to describe metavariable types. + +`tt` (Token Tree): Matches a single token or multiple tokens within matching delimiters `()`, `[]`, or `{}`. + +While there are many other metavariable types, the `tt` type is the most flexible. You can think of it as a "catch-all" metavariable type. + +## Building a DSL Example + +```rust,editable +macro_rules! SQL{ +// `expr` matches an expression. +(SELECT $e:expr;)=>{ + println!("Value: {}", $e); +}; + +// `ident` matches a single identifier. +(SELECT * FROM $t:ident)=>{ + println!("Table: {}", $t); +}; + +// Catch-all case. This uses repetition, which will be introduced in the next chapter. +($($t:tt)*) => { + print!("Unknown: "); + $( + print!("{} ", stringify!($t)); + )* + println!(); + }; +} +fn main(){ + SQL!(SELECT (3+2*4);); + let user_table="USER_TABLE"; + SQL!(SELECT * FROM user_table); + SQL!(SELECT 1+1 AS total FROM "USER_TABLE" WHERE id > 10); +} +``` + +> [!TIP] +> Always use the most specific metavariable type possible. For example, if you only need to match a single identifier, use `ident` instead of `tt`. + +## The Built-in `$crate` Metavariable + +`$crate` is a built-in metavariable that always expands to the name of the crate being compiled. + +```rust,editable +mod utils{ + pub const message: &'static str="Hello, world!"; +} +macro_rules! greet{ + () => { + println!("{}!", $crate::utils::message); + }; +} +fn main(){ + greet!(); +} +``` + +## Metavariable Types + +| Type | Description | Example | +| :--- | :--- | :--- | +| `block` | A block expression (code enclosed in braces `{}`). | `{ let x = 5; x }` | +| `expr` | A valid Rust expression. (In Rust 2024, this includes `_` and `const {}`). | `2 + 2`, `f(x)`, `const { 1 + 1 }` | +| `expr_2021` | An expression, but excludes `_` (UnderscoreExpression) and `const {}` (ConstBlockExpression). | `a * b`, `Some(42)` | +| `ident` | An identifier or a keyword. (Excludes `_`, raw identifiers like `r#foo`, and `$crate`). | `count`, `String`, `match` | +| `item` | A Rust item (such as a function, struct, trait, or module). | `fn run() {}`, `struct User { id: u32 }` | +| `lifetime` | A lifetime token. | `'a`, `'static` | +| `literal` | A literal value (optionally prefixed with a minus sign `-`). | `42`, `-10.5`, `"hello"`, `b'a'` | +| `meta` | The contents (the "meta item") found inside an attribute like `#[...]`. | `derive(Debug, Clone)`, `name = "value"` | +| `pat` | A pattern. Since Rust 2021, it allows top-level "or-patterns" (using `\|`). | `Some(x)`, `1..=5`, `_`, `0 \| 1` | +| `pat_param` | A pattern that does **not** allow top-level "or-patterns". | `Some(x)`, `42` | +| `path` | A path (TypePath style). | `std::io`, `self::utils::process` | +| `stmt` | A statement. Usually captures without the trailing semicolon. | `let x = 1`, `drop(y)` | +| `tt` | A **Token Tree**. It can be a single token or tokens inside matching `()`, `[]`, or `{}`. | `!`, `my_var`, `{ 1, 2, 3 }` | +| `ty` | A Rust type. | `i32`, `Vec`, `&'a str` | +| `vis` | A visibility qualifier (this can be empty). | `pub`, `pub(crate)` | diff --git a/src/macros_1.0_reference.md b/src/macros_1.0_reference.md new file mode 100644 index 0000000..d3d037f --- /dev/null +++ b/src/macros_1.0_reference.md @@ -0,0 +1,3 @@ +# Macros 1.0 macro_rules! + +## Metavariable Types From 84dac438622529976c4d7a495638880da0b51309 Mon Sep 17 00:00:00 2001 From: Atliac Date: Sat, 14 Mar 2026 21:07:00 +0800 Subject: [PATCH 3/3] docs(intro): refine content and simplify summary structure - Improve wording and formatting in prerequisites and reading order sections. - Simplify `SUMMARY.md` by removing redundant headers and reference links. - Update "What You'll Learn" list to better reflect current content. --- src/SUMMARY.md | 8 -------- src/introduction.md | 11 +++++------ src/macros_1.0_reference.md | 2 -- 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 7c040ee..aaa0edf 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -2,15 +2,7 @@ [Introduction](./introduction.md) -# Tutorial - - [Macros 1.0: macro_rules!](./macros_1.0.md) - [Metavariables](./macros_1.0/metavariables.md) - [Macros 2.0]() - [Procedural macros](./procedural_macros.md) - -# Reference - -- [Macros 1.0 `macro_rules!`](./macros_1.0_reference.md) -- [Macros 2.0]() -- [Procedural macros]() diff --git a/src/introduction.md b/src/introduction.md index 278f131..980af3e 100644 --- a/src/introduction.md +++ b/src/introduction.md @@ -4,11 +4,11 @@ Welcome Rustacean! Let's learn about Rust macros. ## Prerequisites -To follow this tutorial, you should have: +To get the most out of this tutorial, we recommend having: -- Basic knowledge of Rust (variables, functions, structs, etc.) -- A working Rust project setup (using `cargo`) -- Understanding of Rust's type system and ownership +- **Familiarity with basic Rust syntax** (variables, functions, and structs). +- **A functional Rust development environment** (with `cargo` installed). +- **A solid understanding** of Rust's core concepts, such as the type system and ownership. If you're new to Rust, consider completing the official [Rust Book](https://doc.rust-lang.org/book/) first. @@ -36,7 +36,6 @@ Rust has two main kinds of macros: ## What You'll Learn In this tutorial, you will learn: -- How macros work under the hood - How to write your own macros - Best practices for macro safety and maintainability - Common macro patterns used in the Rust ecosystem @@ -47,7 +46,7 @@ This tutorial is designed to be interactive and hands-on. Here's how to get the ### Reading Order -It is recommended to read the "Tutorial" section in order. While you can explore other sections, macros build on concepts progressively, and following the intended sequence will help you understand the material better. +For the best learning experience, we recommend reading this tutorial in order. While you are free to explore different sections, macros build on concepts progressively; following the intended sequence will help you understand the material more effectively. ### Interactive Code Blocks diff --git a/src/macros_1.0_reference.md b/src/macros_1.0_reference.md index d3d037f..8d3c6ad 100644 --- a/src/macros_1.0_reference.md +++ b/src/macros_1.0_reference.md @@ -1,3 +1 @@ # Macros 1.0 macro_rules! - -## Metavariable Types