كيف تجتاز مقابلة Rust: أسئلة وأجوبة متقدمة

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

كيف تجتاز مقابلة Rust: أفضل الأسئلة المتقدمة

\n\n

Rust هي لغة برمجة نظامية تكتسب شعبية بفضل أمانها وأدائها وعدم وجود جامع للقمامة. إذا كنت قد أتقنت الأساسيات وتستعد لمقابلة لوظيفة مطور Rust كبير أو متوسط، فستواجه أسئلة تتجاوز النحو البسيط. في هذه المقالة، سنناقش الموضوعات المتقدمة الرئيسية التي تظهر غالبًا في المقابلات التقنية.

\n\n

سنغطي أربعة أقسام: الملكية والاقتراض (ownership & borrowing)، الأعمار (lifetimes)، الكود غير الآمن (unsafe) والماكرو، بالإضافة إلى تعدد الخيوط المتقدم. يحتوي كل قسم على أسئلة حقيقية وأمثلة برمجية.

\n\n

1. الملكية والاقتراض وقواعد القابلية للتغيير

\n\n

السؤال: اشرح كيف تعمل آلية الملكية في Rust. ما الفرق بين &T و &mut T و Box<T>؟

\n\n

الإجابة: الملكية هي أساس أمان الذاكرة في Rust. كل قيمة لها مالك واحد بالضبط. عندما يخرج المالك عن النطاق، يتم تدمير القيمة. الاقتراض (&T) يسمح بـ "استعارة" مؤقتة لمرجع إلى البيانات دون نقل الملكية. الاقتراض القابل للتغيير (&mut T) يعطي الحق في تعديل البيانات، ولكن فقط في حالة عدم وجود مراجع أخرى.

\n\n

Box<T> هو مؤشر ذكي يخصص الذاكرة في الكومة. ينقل الملكية، مما يميزه عن المراجع البسيطة.

\n\n
fn main() {\n    let mut s = String::from("مرحباً");\n    let r1 = &s;      // مرجع غير قابل للتغيير\n    let r2 = &mut s;  // خطأ! لا يمكن وجود &mut و & معًا\n    // println!("{}", r1);\n}\n
\n\n

السؤال: ما هي "قاعدة الاقتراض القابل للتغيير الواحد"؟

\n\n

الإجابة: في أي لحظة، يمكن أن يكون للقيمة إما مرجع واحد قابل للتغيير أو أي عدد من المراجع غير القابلة للتغيير، ولكن ليس كليهما في نفس الوقت. هذا يمنع سباقات البيانات في مرحلة التجميع.

\n\n

2. الأعمار (Lifetimes) - كيف يفهم المترجم أن المرجع لا يزال حيًا

\n\n

السؤال: لماذا نحتاج إلى تعليقات الأعمار؟ أعط مثالًا عندما تكون إلزامية.

\n\n

الإجابة: تساعد تعليقات العمر ('a و 'b إلخ) المترجم في التحقق من صحة جميع المراجع. تكون إلزامية عندما تُرجع الدالة مرجعًا مرتبطًا بأحد معاملات الإدخال، ولا يستطيع المترجم استنتاج العمر تلقائيًا.

\n\n
// دالة تُرجع أطول سلسلة\nfn longest<'a>(x: &'a str, y: &'a str) -> &'a str {\n    if x.len() > y.len() { x } else { y }\n}\n\nfn main() {\n    let s1 = String::from("طويلة");\n    let result;\n    {\n        let s2 = String::from("قصيرة");\n        result = longest(&s1, &s2); // صحيح\n    }\n    // println!("{}", result); // خطأ: s2 ماتت\n}\n
\n\n

السؤال: ما هو "إسقاط العمر" (lifetime elision)؟

\n\n

الإجابة: يضيف المترجم تلقائيًا تعليقات العمر في الحالات البسيطة. على سبيل المثال، بالنسبة للدالة fn first_word(s: &str) -> &str، يفهم المترجم أن عمر الإخراج يساوي عمر الإدخال. يعمل الإسقاط وفقًا لثلاث قواعد موصوفة في كتاب Rust.

\n\n

3. Rust غير الآمن والماكرو

\n\n

السؤال: متى يكون استخدام unsafe مبررًا؟ ما العمليات المتاحة فقط داخل كتل unsafe؟

\n\n

الإجابة: يُستخدم unsafe للعمليات التي لا يستطيع المترجم التحقق منها: إلغاء مرجعية المؤشرات الخام، استدعاء الدوال الخارجية (FFI)، الوصول إلى المتغيرات الثابتة القابلة للتغيير، تنفيذ السمات غير الآمنة. ومع ذلك، فإن unsafe ل

المدونات

توصيات الكتب