extern crate و use في Rust: الفرق الحقيقي وكيف تتجنب الأخطاء
\n\nإذا كنت قد كتبت أي سطر من كود Rust من قبل، فبالتأكيد صادفت التعابير extern crate و use. للوهلة الأولى، قد يبدو أنهما يقومان بنفس المهمة — استيراد كود خارجي. لكن الفرق، كما هو الحال دائمًا، يكمن في التفاصيل. هذا السؤال من أكثر الأسئلة شيوعًا على Stack Overflow (آلاف المشاهدات!)، والمبتدئون يخلطون بينهما باستمرار. دعنا نوضح الفرق بين extern crate و use مرة واحدة وإلى الأبد، وأين يحدث السحر، وكيف تتجنب الأخطاء النمطية.
باختصار: ما هو كل منهما
\n\nتخيل أن مشروعك في Rust هو منزل كبير. extern crate هو توصيل مواد البناء إلى الموقع. أنت تقول للمُجمّع: "مرحبًا، هذا الصندوق من الطوب (الـ crate) أريد استخدامه، أحضره". بدون هذا الأمر، لن يعرف المُجمّع حتى بوجود المكتبة الخارجية.
use هو التنقل الداخلي داخل المنزل. أنت تقول: "أريد أن يؤدي الباب من هذه الغرفة (الوحدة) مباشرة إلى المطبخ (نوع معين أو دالة)". use ينشئ أسماء مستعارة (مسارات مختصرة) للوحدات والأنواع المعروفة بالفعل، حتى لا تضطر لكتابة المسار الكامل في كل مرة.
ببساطة: extern crate يجيب على السؤال "ما الذي يمكننا استخدامه بشكل عام؟"، بينما use يجيب على "كيف يمكننا الوصول إليه بسهولة؟".
السياق التاريخي: لماذا يحدث الخلط
\n\nالخلط لم يحدث من فراغ. في الإصدارات القديمة من Rust (قبل 2018 edition)، كان extern crate إلزاميًا لأي crate خارجي. كان الأمر يبدو هكذا:
// Rust 2015 — الطريقة القديمة\nextern crate serde;\nuse serde::{Serialize, Deserialize};\n\nابتداءً من Rust 2018 edition، أصبح المُجمّع قادرًا على العثور على التبعيات من Cargo.toml بنفسه. الآن، لم يعد من الضروري كتابة extern crate لمعظم الـ crates. يكفي فقط إضافة التبعية في Cargo.toml واستخدام use مباشرة:
// Rust 2018+ — الطريقة الجديدة (extern crate غير إلزامي)\nuse serde::{Serialize, Deserialize};\n\nهنا يبدأ العذاب للمبتدئين. يرون أمثلة قديمة حيث يُستخدم extern crate، وأمثلة جديدة بدونه، ويحاولون فهم متى يكون ضروريًا. تحذير: ضروري، ولكن في حالات نادرة جدًا.
متى لا يزال extern crate ضروريًا (وهذا مهم!)
\n\nهناك ثلاث حالات لا يمكنك فيها الاستغناء عن extern crate:
- \n
- الربط مع المكتبات النظامية عبر
#[link]— إذا كنت تكتب روابط لكود C/C++ وتستخدم الخاصية#[link(name = "sqlite3")]، فإنextern crateإلزامي. \n - الماكروات العامة (Global macros) — بعض الـ crates (مثل
log) تُصدر ماكروات يجب أن تكون مرئية في جميع أنحاء البرنامج. في Rust 2018، تحتاج لكتابةextern crate log;لهذا الغرض. \n - البناء بأسماء crates غير قياسية — إذا كنت تستخدم
extern crate my_crate as foo;لإعادة تسمية الـ crate. \n
في جميع الحالات الأخرى، extern crate هو مجرد أثر من الماضي. لكن العديد من المطورين ما زالوا يكتبونه بدافع العادة، والمبتدئون ينسخون الكود من الدروس القديمة.
أهم 5 أخطاء عند العمل مع extern crate و use
\n\nالخطأ رقم 1: استخدام extern crate حيث لا داعي له
\n\nالمشكلة الأكثر شيوعًا. تضيف crate إلى Cargo.toml، ثم تكتب extern crate rand; — والكود يعمل. لكن هذا سطر زائد. في المشاريع الحديثة (Rust 2018+)، هو فقط يلوّث الكود وقد يربك المطورين الآخرين.
// سيء (زائد عن الحاجة في Rust 2018+)\nextern crate rand;\nuse rand::Rng;