مقدمة: لماذا تعتبر حلقة for العكسية في Rust فخاً للمبتدئين؟
\n\nتخيل الموقف: تنتقل من Python إلى Rust. كل شيء يبدو واضحاً، ولكن عندما تحتاج إلى المرور عبر مصفوفة بترتيب عكسي - تكتب for i in 0..10 وتكتشف بدهشة أن Rust يتجه للأمام فقط. تحاول كتابة for i in 10..0 - وتحصل على حلقة فارغة. هل هذا مألوف؟ إذا كان الأمر كذلك، فأنت لست وحدك. سؤال «How to make a reverse ordered for loop» على Stack Overflow حصد آلاف المشاهدات، وهذا ليس مفاجئاً.
في هذه المقالة، سنحلل أهم الأخطاء التي يرتكبها المبتدئون عند العمل مع الحلقات العكسية في Rust، ونوضح كيفية تجنبها. ستتعرف على سبب عدم عمل 10..0، وكيفية استخدام طريقة .rev() والمكررات، وكذلك كيفية عدم كسر الكود الخاص بك عند العمل مع المتجهات والشرائح. هيا بنا!
الخطأ رقم 1: الاستخدام الساذج للنطاق في الاتجاه العكسي
\n\nالخطأ الأكثر شيوعاً هو محاولة كتابة for i in 10..0 على أمل أن يفهم Rust: «آه، المستخدم يريد الذهاب بترتيب عكسي». للأسف، في Rust، النطاق a..b يذهب دائماً من a إلى b غير شامل. إذا كان a >= b، فإن النطاق فارغ.
// ❌ خطأ: حلقة فارغة\nfor i in 10..0 {\n println!("{}", i); // لن يطبع شيئاً\n}\n\nلماذا هذا؟ Rust لغة صارمة. النطاقات لا تعرف كيفية الانعكاس تلقائياً. هذا من أجل الأداء والقدرة على التنبؤ. إذا كان 10..0 يعمل كعكس، لكان على المترجم التحقق من كل رقم «هل القيمة الأولية أكبر من النهائية؟»، مما يبطئ الحلقات العادية.
كيفية الإصلاح: استخدم طريقة .rev()
\n\nالطريقة الصحيحة هي إنشاء نطاق تصاعدي عادي، ثم استدعاء طريقة .rev() التي تعكس المكرر:
// ✅ صحيح: نستخدم .rev()\nfor i in (0..10).rev() {\n println!("{}", i); // سيطبع: 9, 8, 7, ..., 0\n}\n\nلاحظ: نستخدم (0..10).rev()، وليس 10..0. الأقواس إلزامية، لأن 0..10.rev() سيستدعي الطريقة على 10، وليس على النطاق. هذا خطأ شائع آخر.
الخطأ رقم 2: نسيان الأقواس حول النطاق
\n\nطريقة .rev() تُستدعى على المكرر. النطاق 0..10 هو مكرر. ولكن إذا كتبت 0..10.rev()، سيفسرها Rust كـ 0..(10.rev())، والعدد الصحيح 10 ليس لديه طريقة rev(). سيعطي المترجم خطأ:
// ❌ خطأ في الترجمة: العدد ليس لديه طريقة rev()\nfor i in 0..10.rev() {\n // error[E0599]: no method named `rev` found for integer `i32`\n}\n\nالحل بسيط - استخدم الأقواس المستديرة:
\n\n// ✅ الأقواس تحل كل شيء\nfor i in (0..10).rev() {\n println!("{}", i);\n}\n\nالخطأ رقم 3: محاولة عكس شيء ليس مكرراً
\n\nأحياناً يحاول المبتدئون تطبيق .rev() على متجه أو مصفوفة مباشرة:
let numbers = vec![1, 2, 3, 4, 5];\n\n// ❌ خطأ: Vec ليس لديه طريقة rev()\nfor i in numbers.rev() {\n println!("{}", i);\n}\n\n.rev() هي طريقة للمكرر، وليست للمجموعة. لعكس متجه، يجب أولاً الحصول على مكرر باستخدام .iter() أو .into_iter()، ثم استدعاء .rev():
let numbers = vec![1, 2, 3, 4, 5];\n\n// ✅ صحيح: نحصل على مكرر، ثم نعكسه\nfor i in numbers.iter().rev() {\n println!("{}", i); // سيطبع: 5, 4, 3, 2, 1\n}\n\nإذا كنت بحاجة إلى امتلاك العناصر (مثلاً، نقلها)، استخدم .into_iter().rev():
let numbers = vec![1, 2, 3, 4, 5];\n\nfor i in numbers.into_iter().rev() {\n println!("{}", i); // numbers الآن