الشرائح (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
مباشرةً؟
-
نقوم بإنشاء شريحة (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) منi32
s. لاحظ أن نوعs
(&[i32]
) لم يعد يذكر طول المصفوفة. هذا يسمح لنا بإجراء العمليات الحسابية على شرائح (slices) بأحجام مختلفة. -
الشرائح (Slices) تستعير دائمًا من كائن آخر. في هذا المثال، يجب أن يبقى
a
موجودًا (في النطاق) على الأقل طالما أن شريحتنا (slice) موجودة. -
السؤال حول تعديل
a[3]
يمكن أن يثير نقاشًا مثيرًا للاهتمام، ولكن الإجابة هي أنه لأسباب تتعلق بسلامة الذاكرة (memory safety) لا يمكنك القيام بذلك من خلالa
في هذه المرحلة من التنفيذ (execution)، ولكن يمكنك قراءة البيانات من كل منa
وs
بأمان. يعمل ذلك قبل إنشاء الشريحة (slice)، ومرة أخرى بعدprintln
، عندما لا يتم استخدام الشريحة (slice) بعد الآن.