الشرائح (Slices)

تعطيك الشريحة (slice) نظرة على مجموعة أكبر:

fn main() {
    let mut a: [i32; 6] = [10, 20, 30, 40, 50, 60];
    println!("a: {a:?}");

    let s: &[i32] = &a[2..4];

    println!("s: {s:?}");
}
  • تستعير الشرائح (Slices) البيانات من النوع المقطوع (sliced type).
  • سؤال: ماذا يحدث إذا قمت بتعديل a[3] قبل طباعة s مباشرةً؟
This slide should take about 10 minutes.
  • نقوم بإنشاء شريحة (slice) عن طريق استعارة a وتحديد الفهارس (indexes) البداية والنهاية بين الأقواس.

  • إذا بدأت الشريحة (slice) عند الفهرس 0، فإن صيغة النطاق (range syntax) في Rust تسمح لنا بإسقاط فهرس البداية، مما يعني أن &a[0..a.len()] و &a[..a.len()] متطابقتان.

  • ينطبق نفس الشيء على الفهرس الأخير، لذا فإن &a[2..a.len()] و &a[2..] متطابقتان.

  • لإنشاء شريحة (slice) بسهولة من المصفوفة الكاملة، يمكننا استخدام &a[..].

  • s هو مرجع لشريحة (slice) من i32s. لاحظ أن نوع s (&[i32]) لم يعد يذكر طول المصفوفة. هذا يسمح لنا بإجراء العمليات الحسابية على شرائح (slices) بأحجام مختلفة.

  • الشرائح (Slices) تستعير دائمًا من كائن آخر. في هذا المثال، يجب أن يبقى a موجودًا (في النطاق) على الأقل طالما أن شريحتنا (slice) موجودة.

  • السؤال حول تعديل a[3] يمكن أن يثير نقاشًا مثيرًا للاهتمام، ولكن الإجابة هي أنه لأسباب تتعلق بسلامة الذاكرة (memory safety) لا يمكنك القيام بذلك من خلال a في هذه المرحلة من التنفيذ (execution)، ولكن يمكنك قراءة البيانات من كل من a و s بأمان. يعمل ذلك قبل إنشاء الشريحة (slice)، ومرة أخرى بعد println، عندما لا يتم استخدام الشريحة (slice) بعد الآن.