وحدات الماكرو الإجرائية: Derive وFunction
تعمّقوا في وحدات الماكرو الإجرائية، بما فيها وحدات الماكرو المخصّصة `#[derive]` ووحدات الماكرو الشبيهة بالدوال، لتوليد شيفرة أكثر تعقيدًا.
وحدات الماكرو الإجرائية: Derive وFunction درس مجاني في Learn Rust Coding على CoddyKit. هذا هو الدرس 2 من أصل 3. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Learn Rust Coding، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Learn Rust Coding 3 دروس في المجموع.
مقدمة إلى وحدات الماكرو الإجرائية
مرحبًا بك في عالم وحدات الماكرو الإجرائية! بخلاف وحدات الماكرو التصريحية (macro_rules!)، تشبه وحدات الماكرو الإجرائية الدوال التي تعمل على شِفرة Rust نفسها.
تأخذ TokenStream كإدخال، وتعالجه، ثم تعيد TokenStream أخرى. وهذا يتيح توليد شِفرة أكثر تعقيدًا بكثير.
أنواع وحدات الماكرو الإجرائية
يوفّر Rust ثلاثة أنواع رئيسية من وحدات الماكرو الإجرائية:
- وحدات الماكرو الشبيهة بالدوال: تبدو كاستدعاءات الدوال العادية وتعمل مثلها، مثل
my_macro!(...). - وحدات ماكرو الاشتقاق: تتيح لك تطبيق السمات تلقائيًا على البُنى والتعدادات باستخدام
#[derive(MyTrait)]. - وحدات ماكرو السمات: تتيح لك تعريف سمات مخصصة يمكن تطبيقها على العناصر، مثل
#[route("/path")].
صندوق `proc-macro`
يجب أن توجد وحدات الماكرو الإجرائية في صندوق ذي نوع خاص بها. في ملف Cargo.toml، تعلن عنه كما يلي:
يخبر ذلك Cargo بأن الصندوق يحتوي على وحدات ماكرو تحوّل الشفرة وقت الترجمة.
[package]
name = "my_macros"
version = "0.1.0"
edition = "2021"
[lib]
proc-macro = trueشرح وحدات الماكرو الشبيهة بالدوال
تُعرّف وحدات الماكرو الشبيهة بالدوال باستخدام السمة #[proc_macro] على دالة تستقبل proc_macro::TokenStream وتعيد قيمة من النوع نفسه.
وهي مفيدة للغات الخاصة بالمجال (DSLs) أو لتكرار الشفرة المعقد الذي لا تستطيع macro_rules! معالجته.
use proc_macro::TokenStream;
#[proc_macro]
pub fn my_function_macro(input: TokenStream) -> TokenStream {
// Logic to transform input TokenStream
// ...
input // For example, return the input unchanged
}مثال على ماكرو شبيه بالدوال
إليك مثالًا تصوريًا: ماكرو `greet_name!` ينشئ تعليمة طباعة. سيتعين على التنفيذ الفعلي تحليل إدخال TokenStream لاستخراج الاسم.
ورغم تعقيد تعريف الماكرو، فإن استخدامه بسيط وقوي:
/* In 'my_macros/src/lib.rs' */
use proc_macro::TokenStream;
#[proc_macro]
pub fn greet_name(input: TokenStream) -> TokenStream {
// Imagine parsing 'input' to get a name like 'World'
// and generating: println!("Hello, World!");
"println!(\"Hello, {}!\", \"CoddyKit\");".parse().unwrap()
}
/* In 'my_app/src/main.rs' */
use my_macros::greet_name;
fn main() {
greet_name!("CoddyKit");
}فهم وحدات ماكرو `#[derive]`
وحدات ماكرو الاشتقاق هي النوع الأكثر شيوعًا. وهي تتيح لك تطبيق سمة تلقائيًا على بنية أو تعداد.
عندما تكتب #[derive(Debug)]، يعمل ماكرو وقت الترجمة لتوليد الشفرة اللازمة لكي يطبّق نوعك السمة Debug.
تنفيذ `#[derive]` (مفهوميًا)
تُبنى وحدات ماكرو الاشتقاق المخصصة عادةً باستخدام مكتبات مثل syn (لتحليل شِفرة Rust إلى AST) وquote (لتوليد شِفرة Rust من AST).
ستعرّف دالةً مشروحة بالسمة #[proc_macro_derive(MyTrait)] تستقبل TokenStream تمثّل البنية أو التعداد، ثم تعيد تطبيق السمة المُولَّد.
/* In 'my_macros/src/lib.rs' */
use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput};
use quote::quote;
#[proc_macro_derive(MyDebug)] // MyDebug is the trait name
pub fn my_debug_derive(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput);
let name = &ast.ident;
let expanded = quote! {
impl std::fmt::Debug for #name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct(stringify!(#name)).finish()
}
}
};
expanded.into()
}مثال على استخدام `#[derive(Debug)]`
لنرَ مثالًا عمليًا على ماكرو اشتقاق يُرجّح أنك استخدمته: Debug. بإضافة #[derive(Debug)] إلى بنيتنا Point، يطبّق Rust السمة Debug تلقائيًا، مما يتيح لنا طباعة محتوياتها بصورة واضحة.
#[derive(Debug)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let p = Point { x: 10, y: 20 };
println!("My point is: {:?}", p);
}وحدات ماكرو السمات: `#[my_attribute]`
وحدات ماكرو السمات تشبه وحدات ماكرو الاشتقاق، لكن يمكن تطبيقها على أي عنصر (الدوال والبُنى والوحدات وغير ذلك). وهي تتلقى العنصر المرتبطة به، إضافةً إلى أي وسيطات بين قوسين، كمدخلات.
تشمل الاستخدامات الشائعة توجيه أطر الويب (مثل #[get("/users")]) أو إعداد الاختبارات (مثل #[test]).
/* In 'my_macros/src/lib.rs' */
use proc_macro::TokenStream;
#[proc_macro_attribute]
pub fn log_calls(attr: TokenStream, item: TokenStream) -> TokenStream {
// Imagine adding println! statements to 'item'
item
}
/* In 'my_app/src/main.rs' */
use my_macros::log_calls;
#[log_calls("entry_point")]
fn my_function() {
println!("Inside my_function");
}
fn main() {
my_function();
}متى تستخدم كل نوع من وحدات الماكرو
- وحدات الماكرو الشبيهة بالدوال: للغات المصغّرة المخصّصة أو التحويلات المعقدة لكتل التعليمات البرمجية العشوائية.
- وحدات ماكرو الاشتقاق: لتنفيذ السمات تلقائيًا على البُنى والتعدادات.
- وحدات ماكرو السمات: لتعديل التعليمات البرمجية أو إنشائها حول عناصر محددة (مثل الدوال والبُنى) استنادًا إلى سمات مخصّصة.
لكل نوع غرض فريد في توسيع بنية Rust وإمكاناتها.
اختبار سريع: أنواع وحدات الماكرو
أي العبارات التالية حول وحدات الماكرو الإجرائية صحيحة؟
مراجعة: قوة توليد التعليمات البرمجية
لقد استكشفتم العالم المتقدم لـ وحدات الماكرو الإجرائية!
- تعلّمنا وحدات الماكرو الشبيهة بالدوال لإنشاء بنية مخصّصة.
- فهمنا كيف تعمل وحدات ماكرو
#[derive]على أتمتة تنفيذ السمات. - تعرّفنا بإيجاز على وحدات ماكرو السمات لتوليد التعليمات البرمجية على مستوى العناصر.
تُعد وحدات الماكرو الإجرائية أداة قوية لتقليل التعليمات البرمجية النمطية وتوسيع إمكانات Rust، مما يتيح لكم كتابة تعليمات برمجية تكتب تعليمات برمجية!
الأسئلة الشائعة
هل درس «وحدات الماكرو الإجرائية: Derive وFunction» مجاني؟
نعم — نص درس «وحدات الماكرو الإجرائية: Derive وFunction» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Learn Rust Coding، انتقل إلى CoddyKit PRO. تتضمن دورة Learn Rust Coding 3 دروس في المجموع.
ماذا ستتعلم في «وحدات الماكرو الإجرائية: Derive وFunction»؟
تعمّقوا في وحدات الماكرو الإجرائية، بما فيها وحدات الماكرو المخصّصة `#[derive]` ووحدات الماكرو الشبيهة بالدوال، لتوليد شيفرة أكثر تعقيدًا. تتمرن على Learn Rust Coding مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Learn Rust Coding؟
لا تُشترط خبرة سابقة. Learn Rust Coding على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 3.
كم من الوقت يستغرق درس «وحدات الماكرو الإجرائية: Derive وFunction»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Learn Rust Coding هذا؟
نعم. كل درس في Learn Rust Coding يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- وحدات الماكرو التصريحية (`macro_rules!`)
- وحدات الماكرو الإجرائية: Derive وFunction
- التعامل مع Rust غير الآمنة