محتويات الدورة

Rust / الأساسي / الدرس 4

الاستعارة والشرائح والسلاسل

استخدم وصولًا مؤقتًا دون نقل الملكية، وأنهِ الاستعارات المتعارضة قبل التعديل، وتعامل صراحة مع حدود بايتات UTF-8.

وقت القراءة التقريبي: 4 دقيقةتاريخ مراجعة المحتوى
في هذه الصفحة

أهداف الدرس

  • تمييز الاستعارة المشتركة والقابلة للتعديل الحصرية.
  • استخدام &str والشرائح كواجهات مستعارة.
  • فصل طول البايتات عن عدّ Unicode والمحارف المعروضة.

المرجع يتيح الوصول ولا ينشئ مالكًا

يوفر &T وصولًا مشتركًا إلى T صالحة لعمر مناسب، ويوفر &mut T وصولًا حصريًا قابلًا للتعديل وفق قواعد الاستعارة. لا تملك المراجع التخصيص ولا تمدد عمر مالك اعتباطي. تتعايش استعارات مشتركة، لكن الحصرية النشطة تتعارض مع وصولات أخرى للبيانات نفسها. تتيح أنواع التعديل الداخلي استثناءات مضبوطة بواجهاتها، لا تجاهل قواعد التشارك. حدّد أولًا المراقبة والتعديل ثم اختر المرجع الملائم.

ترتيب الوصول حول آخر استخدام

يتتبع المترجم الاستعارة غالبًا حتى آخر استعمال مناسب بدل إبقائها دائمًا إلى القوس الأخير. يسمح ذلك بالتعديل ثم المراقبة دون كتل زائدة. تستقبل append استعارة حصرية قصيرة وتعود قبل إنشاء شريحة مشتركة، ويبقى المالك حيًا حتى الطباعة. ليس المرجع القابل للتعديل Copy؛ وقد يتضمن تمريره إعادة استعارة، فلا تصف كل استخدام للمراجع كنسخ مطلق. يظهر التوقيع التعديل للمستدعي.

rust مرحلة حصرية تتبعها مراقبة مشتركة
fn append(text: &mut String) { text.push_str(" lab"); }
fn main() {
    let mut title = String::from("Rust");
    append(&mut title);
    let view: &str = &title;
    println!("{view}");
}
الناتج المتوقع
Rust lab

تعدّل append السلسلة المملوكة وتنتهي استعارتها، ثم تستعير &str النص الحي الناتج.

الشريحة تحمل الامتداد مع الاستعارة

تعرض شريحة مثل &[u32] تسلسلًا متجاورًا وطوله دون ملكية. تمثل &str شريحة UTF-8 مستعارة وString سلسلة نامية مملوكة. فضّل &str لمعالمي النص المقروء ليقدم المستدعي نصًا حرفيًا أو سلسلة أو جزءًا صالحًا منها. تحتاج الفهرسة فهرسًا صالحًا وقد تسبب panic، بينما تعيد get قيمة Option للفحص. لا تبقِ الشريحة مستخدمة عبر تعديل متجه قد يبطل تخزينها ولو بدت سعته كافية.

للنص مقاييس طول مختلفة مشروعة

يعد طول String وstr البايتات. وتعد chars قيم Unicode القياسية التي قد تختلف عن الحروف المرئية مع علامات التركيب والسلاسل المتصلة. لا تتيح Rust فهرسة النص بعدد صحيح كأن كل حرف بايت. يجب أن تقع حدود المدى على حدود UTF-8. يستخدم المثال كلمة عربية بثلاث قيم قياسية وستة بايتات ويأخذ أول قيمة ذات بايتين عبر get. يحتاج عد الوحدات المرئية وعرضها إلى سياسة Unicode تتجاوز هذا العرض القياسي.

rust اختلاف البايتات وقيم Unicode
fn main() {
    let word = "نور";
    println!("{} {}", word.len(), word.chars().count());
    if let Some(first) = word.get(0..2) { println!("{first}"); }
}
الناتج المتوقع
6 3
ن

للترميز ستة بايتات وثلاث قيم قياسية، ويمثل 0..2 حدين صالحين للحرف الأول.

تعديل التصميم قبل مقاومة التشخيص

عند تعارض الاستعارة حدّد آخر استعمال لكل مرجع والتعديل المقترح. كثيرًا ما يكفي إكمال القراءة وحفظ نتيجة مملوكة صغيرة ثم التعديل. إذا لزم تعديل جزأين منفصلين معًا تثبت واجهة آمنة مثل split_at_mut عدم تداخلهما. قد يناسب clone لقطة مطلوبة ولا يستبدل فهم التعارض. لا تتحايل بمؤشرات خام على خطأ مبتدئ؛ فهي تنقل الالتزامات إلى unsafe بدل إثبات صلاحية الوصول.

الأخطاء الشائعة وإصلاحها

ظهور E0499 لاستعارتين قابلتين للتعديل متداخلتين.

لماذا يحدث؟
بقي وصولان حصريان نشطين معًا.
كيف تصلحه؟
أنه الأول أو اقسم البيانات المنفصلة بواجهة آمنة.
كيف تتجنب تكراره؟
أبقِ مراحل التعديل قصيرة وصريحة.

ظهور E0502 لتعارض قراءة وتعديل.

لماذا يحدث؟
يُستخدم مرجع مشترك بعد بدء التعديل.
كيف تصلحه؟
أكمل المراقبة قبل الاستعارة القابلة للتعديل.
كيف تتجنب تكراره؟
تتبّع آخر الاستعمالات بدل إضافة أقواس اعتباطية.

رفض مدى بايتات لجزء من نص.

لماذا يحدث؟
يقطع الحد ترميز UTF-8 لمحرف.
كيف تصلحه؟
استخدم حدودًا صالحة أو chars لمعالجة القيم القياسية.
كيف تتجنب تكراره؟
حدّد وحدة النص المطلوبة في المتطلبات.

اختبر فهمك

1. تقرأ دالة اسمًا وتعيد عدد بايتاته مع احتفاظ المستدعي بـString. اكتب التوقيع وتوقع نتيجة "Mira".

اعرض الحل المشروح

استخدم fn byte_count(name: &str) -> usize وأعد name.len(). يستعير byte_count(&owned_name) السلسلة ولا ينقلها. تضم Mira أربعة بايتات ASCII فالنتيجة أربعة. يستطيع المستدعي التعديل بعد انتهاء الاستعارة إذا لم يبقَ مرجع حي منها.

2. فسّر get(0..1) وget(2..4) للكلمة العربية في المثال، وكيف يعالج المستدعي النتيجتين.

اعرض الحل المشروح

تعيد get(0..1) القيمة None لأن الواحد داخل ترميز القيمة الأولى ذي البايتين. وتعطي get(2..4) القيمة Some("و") لوقوع الطرفين حول القيمة الثانية. طابق Option أو استخدم if let بدل unwrap لمدى غير مؤكد. لا تعرّف المديات طريقة عامة لاستخراج حرف مرئي من كل نص Unicode.

أهم ما تعلمته

  • استعر للمدة اللازمة للوصول فقط.
  • عامل &str والشرائح كعروض تعتمد على العمر.
  • اختر البايتات أو القيم القياسية أو الوحدات المرئية صراحة.

المراجع الرسمية