ما يجعل Rust يبدو عدائيًا لمطوري JavaScript ليس التركيب. إنه نموذج العمر.
في JavaScript، عادةً لا تفكر مباشرةً في من يمتلك الذاكرة. إدارة وقت التشغيل وجمع القمامة يتولى ذلك بدلاً منك.
Rust تجبر السؤال على نظام الأنواع.
الملكية في جملة واحدة
لكل قيمة مالك، وعندما يخرج ذلك المالك عن النطاق، يتم إسقاط القيمة.
هذا هو النموذج الأساسي.
ثم يفرض المُجمّع قواعد الاقتراض بحيث لا يمكنك استخدام البيانات عن طريق الخطأ بعد نقلها أو تعديلها من خلال مراجع متضاربة.
الخطأ الأول الذي يراه الجميع
fn print_name(name: String) {
println!("{}", name);
}
fn main() {
let my_name = String::from("Alaeddine");
print_name(my_name);
println!("{}", my_name);
}
هذا يفشل لأن my_name تم نقله إلى print_name.
بالنسبة لمطور JavaScript، فإن هذا يشعر بأنه اعتباطي.
بالنسبة لـ Rust، هذه هي الطريقة التي يتم بها توضيح نقل الملكية.
الاقتراض بدلاً من النقل
إذا كانت الدالة تحتاج فقط لقراءة القيمة، اقترضها:
fn print_name(name: &str) {
println!("{}", name);
}
fn main() {
let my_name = String::from("Alaeddine");
print_name(&my_name);
println!("{}", my_name);
}
الآن تبقى الملكية مع my_name، وتستقبل الدالة مرجعًا بوعد أضيق.
لماذا يوجد ذلك
مدقق الاقتراض لا يحاول أن يجعلك تعاني. إنه يمنع:
- أخطاء الاستخدام بعد التحرير
- سباقات البيانات
- أنماط التسمية غير الصالحة
في الكود الذي كان سيترجم وإلا في لغات منخفضة المستوى ويفشل في وقت التشغيل.
التكلفة البيانية هي مقدمة. الفائدة هي أن فئات كاملة من أخطاء الذاكرة تصبح أخطاء تجميع.
أفضل طريقة لتعلم ذلك
لا تبدأ بحفظ رسائل الأخطاء.
ابدأ بطرح الأسئلة:
- من يملك هذه القيمة؟
- هل أنقلها أم أقترضها؟
- هل تحتاج هذه الدالة إلى الملكية أو التعديل أو مجرد مرجع للقراءة؟
بمجرد أن تصبح تلك الأسئلة طبيعية، تبدأ أخطاء المُجمّع في القراءة كإرشادات بدلاً من عقوبات.
قراءة إضافية