هل Rust مناسبة لهياكل البيانات والخوارزميات؟
لاستخدامها، مناسبة جداً: المجموعات القياسية سريعة وموثّقة جيداً، وsort مستقرة، وRust الآمنة تمنع المؤشرات المعلّقة وسباقات البيانات وقت التصريف، من دون جامع مهملات. أما لكتابة الهياكل القائمة على المؤشرات، فهي أصعب من C أو Java، لأن الملكية تمنع الروابط المشتركة القابلة للتعديل ما لم تلجأ صراحةً إلى Rc وRefCell، والقائمة المترابطة المزدوجة أو الشجرة ذات المؤشرات إلى الآباء مصنوعة من هذه الروابط تحديداً. وهذه الصعوبة هي الدرس أيضاً: حين تستطيع كتابتها بلغة Rust، تعرف بالضبط من يملك ماذا.
أي مجموعات Rust تقابل أي هياكل بيانات؟
Vec<T> مصفوفة ديناميكية ومكدسك، وVecDeque<T> مخزن مؤقت حلقي وطابورك، وHashMap وHashSet جداول تجزئة (بدالة SipHash افتراضياً، وهي تقاوم التصادمات المتعمدة مقابل شيء من السرعة)، وBTreeMap وBTreeSet أشجار B مرتبة، وBinaryHeap<T> كومة عظمى، وLinkedList<T> قائمة مترابطة مزدوجة نادراً ما ستفضّلها على Vec أو VecDeque. ولا يوجد نوع لشجرة البادئات أو للرسم البياني؛ فهذان تبنيهما أنت.
لماذا يصعب أن تكتب قائمة مترابطة بلغة Rust إلى هذا الحد؟
لأن لكل قيمة مالكاً واحداً بالضبط. القائمة المترابطة الأحادية تتوافق مع هذه القاعدة: كل عقدة تملك التالية عبر Option<Box<Node>>. أما القائمة المترابطة المزدوجة أو الشجرة ذات الروابط إلى الآباء فلا تتوافق معها، لأن مؤشرين يقودان إلى كل عقدة، فتلجأ إلى Rc<RefCell<Node>> مع Weak للروابط العكسية، أو تحفظ العقد في Vec وتربط بينها بالفهارس. ودليل Learning Rust With Entirely Too Many Linked Lists موجود لأن كثيرين يتعثرون هنا تحديداً.
كيف أحصل على كومة صغرى في Rust؟
BinaryHeap<T> كومة عظمى، لذا غلّف كل عنصر في std::cmp::Reverse: أضف Reverse(x) وسيخرج أصغر x أولاً. وفي Dijkstra أضف Reverse((distance, node))، فيُقارَن الـ tuple بالمسافة أولاً. وبعد أن تكتب كومة بنفسك في الخطوة الثانية، يصبح قلب ترتيبها أمراً بديهياً.
ما الدورات في هذا المسار التي لا تُدرَّس بلغة Rust؟
ثلاث دورات. البرمجة الديناميكية وسلسلة مقابلات Python تُدرَّسان بلغة Python، وعمليات البتات بلغة C++. وتجدها مُدرجة بعد الخطوات، ولكل منها رابط يفتحها بلغتها. جدول النتائج المحفوظة في Rust يكون Vec أو HashMap، وفيضان الأعداد الصحيحة يسبّب panic في بناء التصحيح (debug build)، لذا فحيلة البتات التي تعتمد على الالتفاف (wrapping) تصرّح بذلك عبر wrapping_add أو wrapping_mul.
هل أحتاج إلى معرفة Rust قبل بدء هذا المسار؟
الملكية والاستعارة (ownership وborrowing) والبُنى (structs) والتعدادات (enums) وOption على الأقل؛ وBox والـ traits تفيد. إن كانت هذه جديدة عليك، فدورة Rust من Coddy توصلك إلى ذلك أولاً مجاناً، ويبدأ هذا المسار من حيث تنتهي.