حلقة for العكسية في Rust: كيف لا تقع في أخطاء المبتدئين

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

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

ابدأ الدورة

مقدمة: لماذا تعتبر حلقة 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 حصد آلاف المشاهدات، وهذا ليس مفاجئاً.

\n\n

في هذه المقالة، سنحلل أهم الأخطاء التي يرتكبها المبتدئون عند العمل مع الحلقات العكسية في Rust، ونوضح كيفية تجنبها. ستتعرف على سبب عدم عمل 10..0، وكيفية استخدام طريقة .rev() والمكررات، وكذلك كيفية عدم كسر الكود الخاص بك عند العمل مع المتجهات والشرائح. هيا بنا!

\n\n

الخطأ رقم 1: الاستخدام الساذج للنطاق في الاتجاه العكسي

\n\n

الخطأ الأكثر شيوعاً هو محاولة كتابة for i in 10..0 على أمل أن يفهم Rust: «آه، المستخدم يريد الذهاب بترتيب عكسي». للأسف، في Rust، النطاق a..b يذهب دائماً من a إلى b غير شامل. إذا كان a >= b، فإن النطاق فارغ.

\n\n
// ❌ خطأ: حلقة فارغة\nfor i in 10..0 {\n    println!("{}", i); // لن يطبع شيئاً\n}
\n\n

لماذا هذا؟ Rust لغة صارمة. النطاقات لا تعرف كيفية الانعكاس تلقائياً. هذا من أجل الأداء والقدرة على التنبؤ. إذا كان 10..0 يعمل كعكس، لكان على المترجم التحقق من كل رقم «هل القيمة الأولية أكبر من النهائية؟»، مما يبطئ الحلقات العادية.

\n\n

كيفية الإصلاح: استخدم طريقة .rev()

\n\n

الطريقة الصحيحة هي إنشاء نطاق تصاعدي عادي، ثم استدعاء طريقة .rev() التي تعكس المكرر:

\n\n
// ✅ صحيح: نستخدم .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، وليس على النطاق. هذا خطأ شائع آخر.

\n\n

الخطأ رقم 2: نسيان الأقواس حول النطاق

\n\n

طريقة .rev() تُستدعى على المكرر. النطاق 0..10 هو مكرر. ولكن إذا كتبت 0..10.rev()، سيفسرها Rust كـ 0..(10.rev())، والعدد الصحيح 10 ليس لديه طريقة rev(). سيعطي المترجم خطأ:

\n\n
// ❌ خطأ في الترجمة: العدد ليس لديه طريقة 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() على متجه أو مصفوفة مباشرة:

\n\n
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():

\n\n
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():

\n\n
let numbers = vec![1, 2, 3, 4, 5];\n\nfor i in numbers.into_iter().rev() {\n    println!("{}", i); // numbers الآن                

المدونات

توصيات الكتب