وحدات الماكرو التصريحية (`macro_rules!`)
تعلّموا كتابة وحدات ماكرو تصريحية لتجريد أنماط الشيفرة المتكررة وتوليد الشيفرة أثناء الترجمة.
وحدات الماكرو التصريحية (`macro_rules!`) درس مجاني في Learn Rust Coding على CoddyKit. هذا هو الدرس 1 من أصل 3. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Learn Rust Coding، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Learn Rust Coding 3 دروس في المجموع.
بعض أجزاء هذا الدرس لم تُترجم بعد وتظهر باللغة الإنجليزية.
What are Rust Macros?
Macros are a way to write code that writes code! They're like functions, but they operate on syntax trees (the structure of your code) instead of values.
- They help abstract repetitive code.
- They enable Domain Specific Languages (DSLs) within Rust.
- They run at compile time, expanding into regular Rust code before compilation.
Declarative Macro Syntax
Rust's declarative macros use the macro_rules! keyword. They define a set of rules that match specific patterns of Rust code.
Think of it as pattern matching for code snippets. When the compiler sees a macro invocation, it tries to match the input to one of the rules you've defined.
Your First `macro_rules!`
Let's create a very simple macro that prints a greeting. Notice the macro_rules! keyword and the () => {} syntax, defining a rule with no input pattern.
Try running this example:
macro_rules! greet {
() => {
println!("Hello from a macro!");
};
}
fn main() {
greet!(); // Call our macro!
}Capturing Input with Designators
Macros can take input using "designators." These tell the macro what kind of Rust syntax it should expect to capture.
$expr: An expression (e.g.,1 + 2,"hello")$ident: An identifier (e.g., variable name, function name)$ty: A type (e.g.,i32,String)$block: A block of code (e.g.,{ ... })- ...and many more!
Macros Taking Arguments
Here's a macro that takes an expression ($e:expr) and prints its value. The :expr is the designator.
The captured $e then becomes available for use in the macro's body. The stringify! macro converts the expression into its string representation.
macro_rules! debug_print {
($e:expr) => {
println!("Debug: {} = {:?}", stringify!($e), $e);
};
}
fn main() {
let x = 10;
debug_print!(x + 5);
debug_print!("Rust macros are fun");
}Handling Multiple Inputs
What if you want a macro to take multiple arguments of the same type? You can use repetition operators: $()*.
$(): The content inside is the pattern to repeat.*: Zero or more repetitions.+: One or more repetitions.- You can also specify a separator, like
$(...),*for comma-separated items.
Macro with Repetitive Arguments
Let's create a macro that takes multiple expressions, separated by commas, and prints each one individually. This is powerful for creating list-like structures.
macro_rules! print_all {
( $( $x:expr ),* ) => {
$( // This $(...)* repeats the `println!` call
println!("Item: {:?}", $x);
)*
};
}
fn main() {
print_all!(1, "hello", true, 3.14);
print_all!("Just one item");
}Understanding Macro Hygiene
Rust's macros are "hygienic." This means that variables defined inside a macro won't accidentally clash with variables outside the macro, even if they have the same name.
The compiler renames things internally during expansion to prevent unintended side effects, making macros safer and more predictable to use.
How to Debug Macros
Sometimes macros don't expand as you expect. Rust provides a way to see the expanded code:
- Run
cargo expand(requires installing thecargo-expandtool) - Use
rustc --pretty expandeddirectly on your source file.
This shows you the raw Rust code that your macro generates, which is invaluable for debugging and understanding complex macro behavior!
Macro Pattern Matching Quiz
Consider the following macro definition:
macro_rules! make_tuple {
( $x:expr, $y:expr ) => {
($x, $y)
};
}Which of the following lines would successfully compile and use the make_tuple! macro?
Recap: Declarative Macros
In this lesson, you learned about declarative macros using macro_rules!:
- They generate code at compile time, abstracting repetitive patterns.
- They use pattern matching to capture input based on syntax.
- Designators like
$expr,$identspecify what kind of syntax to expect. - Repetition operators like
$()*handle multiple arguments with flexible separators. - Macros are hygienic, preventing accidental name conflicts.
Macros are a powerful tool for reducing boilerplate and creating flexible, ergonomic APIs in Rust!
الأسئلة الشائعة
هل درس «وحدات الماكرو التصريحية (`macro_rules!`)» مجاني؟
نعم — نص درس «وحدات الماكرو التصريحية (`macro_rules!`)» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Learn Rust Coding، انتقل إلى CoddyKit PRO. تتضمن دورة Learn Rust Coding 3 دروس في المجموع.
ماذا ستتعلم في «وحدات الماكرو التصريحية (`macro_rules!`)»؟
تعلّموا كتابة وحدات ماكرو تصريحية لتجريد أنماط الشيفرة المتكررة وتوليد الشيفرة أثناء الترجمة. تتمرن على Learn Rust Coding مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Learn Rust Coding؟
لا تُشترط خبرة سابقة. Learn Rust Coding على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 3.
كم من الوقت يستغرق درس «وحدات الماكرو التصريحية (`macro_rules!`)»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Learn Rust Coding هذا؟
نعم. كل درس في Learn Rust Coding يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- وحدات الماكرو التصريحية (`macro_rules!`)
- وحدات الماكرو الإجرائية: Derive وFunction
- التعامل مع Rust غير الآمنة