دستور الملكية
Rust

ست عدسات. حين تختلط عليك ميزة جديدة تقابلها بعد هذا المنهج، مرّرها عبر هذه الست قبل أن تحفظ قاعدة نحوية — غالبًا ستجدها امتدادًا لواحدة منها.


١. الأسئلة الثلاثة التي تحكم كل قرار تصميمي

كل قاعدة أمان في Rust جواب على أحد ثلاثة أسئلة، بالترتيب الذي تُطرح به:

  1. من يملك، ومتى يُحرَّر؟ ← البديهية الأولى (٠١): مالك واحد، Drop حتمي.
  2. من يقرأ ومن يكتب الآن؟ ← البديهية الثانية (٠٢): مشاركة XOR تعديل.
  3. متى بالضبط تنتهي كل علاقة استعارة؟ ← الأعمار (٠٥): تسمية صريحة للعلاقات عبر حدود الدوال والبُنى.

أي رسالة خطأ من المترجم تستطيع تصنيفها تحت أحد الثلاثة. حين تُصنّفها صحيحًا، يصبح الإصلاح واضحًا بدل أن يكون تجربة-وخطأ عشوائية.


٢. زيرو-كوست ليست شعارًا — إنها نفس الحركة أربع مرات

في كل مرة رأيتَ فيها Rust "تحلّ مشكلة تجريد"، الحل كان نفس الحركة: لا تمحُ المعلومة وقت التشغيل، بل حوّلها لكود ملموس وقت الترجمة.

التجريدماذا يحدث وقت الترجمةالناتج وقت التشغيل
enum/match (٠٣)التاغ يُثبَّت في تخطيط الذاكرةفحص فعلي، لا وهمي (بعكس erasure TS)
generics (٠٤)monomorphization: نسخة آلة لكل نوع مستعمَلصفر فحص نوع، صفر قفزة إضافية
إغلاقات (٠٦)نوع فريد بحجم = حجم الالتقاط بالضبطمؤشر دالة عادي إن لم يلتقط شيئًا
منتِجات (٠٦)سلسلة .filter().map() تُدمَج لحلقة واحدةصفر تخصيص وسيط
async/.await (١٠)آلة حالة (enum) تُبنى كاملةصفر heap إلا إن طلبتَه، صفر مفسّر

المبدأ الواحد: "ما لا تستعمله لا تدفع ثمنه؛ وما تستعمله، لا تستطيع أن تكتبه يدويًا بكفاءة أعلى." كل ميزة "متقدمة" في هذا المنهج مثال جديد على نفس الجملة، لا فكرة منفصلة.


٣. طيف الثقة: من يثبت الأمان، ومتى؟

مجاني، ترجمة          ثمن صغير، تشغيل           لا فحص، أنت المسؤول
──────────────────────────────────────────────────────────────────►
borrow checker    →    RefCell / Mutex      →      unsafe
(٠١، ٠٢)               (panic عند الخرق، ٠٧)        (UB عند الخرق، ٠٩)

نفس الالتزام بالضبط ("لا alias+mutate معًا") يُفرَض في ثلاث نقاط مختلفة على هذا الطيف. اختيار النقطة قرار هندسي واعٍ: كلما تحرّكتَ يمينًا، كسبتَ مرونة (أنماط لا يستطيع المترجم إثباتها ساكنًا) ودفعتَ ثمنًا (فحص وقت تشغيل، أو مسؤولية كاملة بلا أي فحص). لا نقطة "صحيحة" مطلقًا — فقط مناسبة للسياق.


٤. الثلاثية الواحدة، بثلاثة أزياء

كل مرة رأيتَ فيها "ثلاثة أشكال" لشيء ما في اللغة، كانت نفس ثلاثية البديهيتين، لا صدفة تسمية:

الثلاثة تسأل نفس السؤال بالضبط: تمليك، أم استعارة قراءة، أم استعارة حصرية؟ حين تقابل بناءً جديدًا يبدو "بثلاثة أوضاع"، اسأل أولًا: أهذه الثلاثية نفسها متنكّرة؟ الجواب غالبًا نعم.


٥. Option / Result / Poll — enum واحد، ثلاث دلالات لـ"لا بعد"

enum Option<T> { Some(T), None }        // لا قيمة، ربما أبدًا
enum Result<T, E> { Ok(T), Err(E) }     // قيمة، أو سبب فشل محدَّد
enum Poll<T>      { Ready(T), Pending } // قيمة، أو "ليس الآن — اسأل لاحقًا"

ثلاثتها نفس الشكل الجبري (فرعان، أحدهما يحمل بيانات). الفرق كله في الدلالة التي يحملها الفرع "السلبي": None نهائي، Err معلوماتي (يحمل سببًا)، Pending مؤقت (يعد بمحاولة لاحقة). حين تصمّم enum خاصًا بك لحالة "قد يفشل أو يتأخر"، ابدأ من هذا القالب واسأل: أيّ الثلاثة دلالتي أقرب؟


٦. ترجمان C → Rust (خريطة سريعة لعقلك القديم)

كنتَ تكتبه في Cيقابله هناالفرق الجوهري
malloc/free يدويًاownership + Drop حتمي (٠١)مُثبَت بالمترجم، لا بذاكرتك
union بلا تاغenum (٠٣)التاغ حقيقي، القراءة الخاطئة مستحيلة نحويًا
void* + cast يدوي (qsort)generics + trait bounds (٠٤)فحص نوع كامل وقت الترجمة، صفر UB
مؤشر دالة خامFn/dyn Trait (٠٤، ٠٦)نفس الفكرة، معبّأة بأمان النوع
errno / return -1Result<T, E> + ? (٠٣)جزء من التوقيع، لا يُنسى بصمت
NULLOption<T> (٠٣)absence نوع حقيقي، لا كذبة في كل مؤشر
مؤشر خام + حساب يدوي*const/*mut داخل unsafe فقط (٠٩)نفس القوة، محصورة ومُسمّاة صراحة
pthread + mutex يدويthread/Arc/Mutex (٠٨)نفس القدرة، سباقات البيانات مستحيلة نحويًا غالبًا