الصفوف طريقة خفيفة لتجميع مجموعة ثابتة من البيانات ذات أنواع متعددة معًا. ولا يحمل الصف اسمًا بعينه؛ فتسمية بنية البيانات تحوّلها إلى struct. كما أن حقول الصف بلا أسماء؛ إذ يتم الوصول إليها عبر التفكيك أو عبر الموضع.
تُنشأ الصفوف دائمًا بتعبير صفّي:
// pointless but legal
let unit = ();
// single element
let single_element = ("note the comma",);
// two element
let two_element = (123, "elements can be of differing types");
ويمكن أن يحتوي الصف على أي عدد من العناصر.
يمكن الوصول إلى عناصر الصف عبر التفكيك. وهذا يعني ببساطة إسناد أسماء متغيرات إلى كل عنصر من عناصر الصف، مما يستهلك الصف نفسه.
let (elem1, _elem2) = two_element;
assert_eq!(elem1, 123);
يمكن أيضًا الوصول إلى عناصر الصف عبر فهرس موضعي رقمي. والفهرسة، كما هو الحال دائمًا، تبدأ من 0.
let notation = single_element.0;
assert_eq!(notation, "note the comma");
سيُطلب منك أيضًا العمل مع بنى الصف. ومثل البنى العادية، هذه أنواع مُسمّاة؛ وعلى خلاف البنى العادية، لها حقول مجهولة. وصياغتها شبيهة جدًا بصياغة الصفوف العادية. ويجوز استخدام كلٍّ من التفكيك والوصول عبر الموضع.
struct TupleStruct(u8, i32);
let my_tuple_struct = TupleStruct(123, -321);
let neg = my_tuple_struct.1;
let TupleStruct(byte, _) = my_tuple_struct;
assert_eq!(neg, -321);
assert_eq!(byte, 123);
جميع حقول الصفوف المجهولة عامة دائمًا. أما حقول بنى الصف فلكل حقل منها ظهوره الخاص الذي يكون خاصًّا افتراضيًا، تمامًا كحقول البنى العادية. ويمكنك جعل الحقول عامة باستخدام المُعدِّل pub، تمامًا كما في البنية العادية.
// fails due to private fields
mod tuple { pub struct TupleStruct(u8, i32); }
fn main() { let _my_tuple_struct = tuple::TupleStruct(123, -321); }
// succeeds: fields are public
mod tuple { pub struct TupleStruct(pub u8, pub i32); }
fn main() { let _my_tuple_struct = tuple::TupleStruct(123, -321); }
أنت تعمل على لعبة موجّهة لنظام مضمّن منخفض الطاقة، وتحتاج إلى كتابة عدة دوال مساعدة ستستخدمها أجزاء أخرى من اللعبة.
خارج القسمة هو ناتج عملية القسمة.
fn divmod(dividend: i16, divisor: i16) -> (i16, i16)
مثال:
assert_eq!(divmod(10, 3), (3, 1));
سيُساعدك هذا في تفعيل تحسين المخزن المؤقت للشاشة، كما وعدك مديرك.
المكرِّرات عناصر تعرض الطرق التي يعرّفها trait Iterator. وهذا التوثيق موسّع إلى حد كبير، لأنها تقدّم طرقًا كثيرة؛ إليك أهم خصائصها:
enumerate تُرجع صفًا (i, val) لكل قيمةfilter تستخدم إغلاقًا لتحديد ما إذا كان ينبغي إنتاج عنصر من عناصر المكرِّرmap تستخدم إغلاقًا لتعديل عناصر المكرِّرولأن دالتك يمكن أن تعمل على أي نوع من المكرِّرات، فإنها تستخدم impl للدلالة على أن هذا نموذج لـ trait بدلًا من عنصر بسيط. وبالمثل، تعني صيغة <Item=T> ببساطة أنه لا يهم ما نوع العنصر الذي ينتجه المكرِّر؛ فدالتك قادرة على إنتاج العناصر الزوجية من أي مكرِّر.
fn evens<T>(iter: impl Iterator<Item=T>) -> impl Iterator<Item=T>
أمثلة:
let mut even_ints = evens(0_u8..);
assert_eq!(even_ints.next(), Some(0));
assert_eq!(even_ints.next(), Some(2));
assert_eq!(even_ints.next(), Some(4));
assert_eq!(even_ints.next(), Some(6));
let mut evens_from_odds = evens(1_i16..);
assert_eq!(evens_from_odds.next(), Some(1));
assert_eq!(evens_from_odds.next(), Some(3));
assert_eq!(evens_from_odds.next(), Some(5));
assert_eq!(evens_from_odds.next(), Some(7));
لتسهيل رسم الخرائط، لديك بنية صفية تُسمّى Position:
struct Position(i16, i16);
عليك تنفيذ طريقة manhattan في Position تُرجع مسافة مانهاتن لهذا الموقع من نقطة الأصل (Position(0, 0)).
impl Position {
fn manhattan(&self) -> i16
}
مثال:
assert_eq!(Position(3, 4).manhattan(), 7);
سجّل في Exercism لتتعلّم وتتقن Rust عبر 99 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.