لم Zig اذا كانت هناك لغات مثل ++C وD وRust بالفعل؟
لا تحكمات مخفية في التدفّق
اذا كان الكود ظاهره أنه لا يستدعي وظيفة، فهذا ما يحدث بالفعل. هذا يعني أن بامكانك التأكد من أن الكود التالي يستدعي فقط ()foo
ثم ()bar
، وهذا مضمون دون أن تحتاج معرفة نوع أيًا من المتغيرات:
var a = b + c.d;
foo();
bar();
أمثلة للتحكم المخفي في التدفّق:
- D لديها وظائف
property@
، التي يمكنك استدعائها كما لو كانت حقل لا وظيفة، لذلك في المثال أعلاه يحتمل أن تستدعيc.d
وظيفة. - لدى ++C، وD، وRust خاصية إعادة تعريف المعاملات، لذا فيمكن للمعامل
+
أن يستدعي وظيفة. - لدى ++C، وD، وRust خاصية الاستثناءات، لذا يمكن أن تقوم وظيفة
()foo
برمي استثناء مما يمنع استدعاء وظيفة()bar
. (بالطبع حتى في Zig فيمكن لـ()foo
أن تستعصي مما يمنع استدعاء()bar
، ولكن هذا يمكن أن يحدث في أي لغة متكاملة مع معايير تورنغ).
المقصد من هذا التصميم هو تحسين المقرؤية.
لا تخصيصات مخفية للذاكرة
تتتبع Zig أسلوب عدم التدخل حين يتضمن الأمر تخصيص ذاكرة من الكومة. لا توجد كلمة new
مفتاحية ولا تستعمل أي مزايا في اللغة مُخصص ذاكرة خاص (مثل عامل تكديس السلاسل [1]). ذاكرة الكومة يديرها كود المكتبات والبرنامج، وليس اللغة.
أمثلة على التخصيصات المخفية:
- تُخصِص
defer
في Go ذاكرة من رص محلي. بالإضافة لكونها طريقة غير غير بديهية للتحكم في التدفّق، يمكنها كذلك التسبب في أعطال نتيجة عدم وجود مساحة ذاكرة كافية في حالة استعمالdefer
في حلقة. - الإجراءات الرويتينة في ++C تخصص ذاكرة من الكومة لكي تستطيع استدعاء إجراء روتيني.
- استدعاء وظيفة في Go يمكن أن يتسبب في تخصيص ذاكرة من الكومة لأن إجراءات Go الروتينة تخصص رصات صغيرة يعاد تحديد حجمها إذا تعمق رص الاستدعاء بما يكفي.
- الواجهات البرمجية لمكتبات Rust الأساسية ترتبك عند عدم وجود مساحة ذاكرة كافية، والبدائل التي تقبل بمخصص كمَعلم لم تدرس بعناية (راجع rust-lang/rust#29802)
لدى تقريبًا كل اللغات جامعة المخلفات تخصيصات مخفية، حيث أن جامع المخلفات يخفي أدلة التخصيص عند الجمع.
المشكلة الأساسية في التخصيصات المخفية هي أنها تمنع إعادة استخدام الكود، مما يحصر عدد البيئات التي يمكن استخدام هذا الكود فيها دون داع. ببساطة، هناك حالات استخدام تتطلب الإعتماد على تدفّق التحكم بشكل معين وألا تكون هناك عواقب لاستدعاء الوظائف مثل تخصيص الذاكرة، لذلك لا يمكن للغة برمجة أن تخدم هذه الاستخدامات إلا إذا كانت قادرة على ضمان ما سبق.
في Zig، هناك مزايا في المكتبة الأساسية توفر وتعمل مع مخصصي الأكوام، ولكن تلك مزايا اختيارية ليست جزء من اللغة نفسها. إذا لم تستعمل مخصص أكوام بنفسك، فتأكد أن برنامجك لن يخصص ذاكرة حرة.
تقبل أي ميزة في المكتبة الأساسية من التي تحتاج لتخصيص ذاكرة مَعلم Allocator
كي تستطيع فعل ذلك. هذا يعني أن مكتبة Zig الأساسية تدعم المنصات القائمة بذاتها. على سبيل المثال يمكن استخدام std.ArrayList
و std.AutoHashMap
في البرمجة دون نظام تشغيل!
المخصصون المعدّون حسب الطلب يسهلون من عملية إدارة الذاكرة. لدى Zig مخصص تحليلي يحافظ على أمان الذاكرة عند وقوع حالات استخدام بعد التحرير أو التحرير المزدوج. يقوم برصد وطباعة متفقدات الرص بشكل آلي عند تسرب الذاكرة. يوجد أيضًا مخصص مجالي يمكنك من تجميع أي عدد من التخصيصات في واحدة ويقوم بتحريرهم جميعًا مرة واحدة بدلًا من إدارة كل تخصيص على حدة. المخصصات ذات الإستخدامات الخاصة يمكن استعمالها لتحسين الأداء أو استهلاك الذاكرة حسب متطلبات البرنامج.
[1]: في الواقع هناك معامل تكديس للسلاسل (أو بصورة أعم فهو تكديس للمصفوفات معامل) ولكنه يعمل فقط في زمن التصريف، فلا يقوم بأي عمليات تخصيص في زمن التنفيذ.
دعم من الطراز الأول لعدم وجود مكتبة أساسية
كما أشرنا من قبل، لدى Zig مكتبة أساسية إختيارية بالكامل. كل واجهة مكتبة برمجية يتم تجميعها في برنامجك فقط إذا استعملتها. لدى Zig دعم متساوي للربط بمكتبة libc أوبدونها. Zig ملائمة للمنصات المستقلة والتطوير عالي الأداء.
الأفضل بين عالمين؛ مثلًا في Zig، يمكن لبرامج WebAssembly أن تستعمل المزايا العادية من المكتبة الأساسية، وتحافظ في نفس الوقت على إنتاج أصغر ملفات بالمقارنة بلغات البرمجة الأخرى التي تدعم الترجمة لـWebAssembly.
لغة نقّالة للمكتبات
أحد أهداف البرمجة السامية هي إعادة استعمال الكود. نجد أنفسنا للأسف نعيد إختراع العجلة معظم الوقت. أغلب الوقت يكون هذا مبررًا.
- إذا كان التطبيق فوريًا، فأي مكتبة تستخدم جامعًا للمخلفات أو أي أسلوب ذا تصرف غير حتمي لن تصلح كإعتمادية.
- إذا جعلت اللغة تجاهل الأخطاء سهلًا للغاية، أصبح التأكد من أن المكتبة تتعامل مع الأخطاء بشكل صحيح أمر صعب. يشجع ذلك على تجنب المكتبة بالكامل وإعادة كتابة الكود أملًا في أن يكون الكود الجديد يتعامل مع كل أنواع الأخطاء بشكل صحيح. Zig مصممة بحيث أن أكثر خيارًا كسلًا أمام المبرمج هو التعامل مع الأخطاء بشكل صحيح، لذا يمكنك الوثوق في أن المكتبة تتعامل بشكل صحيح مع الأخطاء.
- حاليًا يمكننا القول أن لغة C هي أكثر لغة نقّالة. أي لغة لا تمتلك القدرة على التفاعل مع C تخاطر أن يطويها النسيان. تسعى Zig أن تكون أكثر لغة برمجة نقّالة للمكتبات عن طريق تبسيط التوافق مع واجهة C الثنائية للوظائف الخارجية، وتقديم سبل الأمان وتصميمات لغوية تمنع أكثر الأخطاء شيوعًا في الوقت نفسه.
مدير حِزم ونظام بناء للمشاريع القائمة
Zig لغة برمجة، ولكنها تُشحن أيضًا بنظام بناء ومدير حِزم بنية أن يكونوا مفيدين حتى في سياق مشاريع ++C/C التقليدية.
ليس بإمكانك كتابة كود Zig بدلًا من C أو ++C فحسب، بل ويمكنك استخدام Zig كبديل لـautotools وcmake وmake وscons وninja، إلخ. علاوة على ذلك (سوف) تقدم Zig مدير حِزم للاعتماديات الأصيلة. الهدف من نظام البناء هذا هو أن يكون ملائمًا حتى ولو كان المشروع بأكمله مكتوبًا بلغة C أو ++C.
لمديري حِزم الأنظمة مثل apt-get وpacman وhomebrew وآخرون دور أساسي في تحديد تجربة المستخدم، ولكنهم في بعض الأحيان لا يكونون كافيين لاحتياجات المطورين. مدير حِزم مخصص لللغة يمكن أن يكون السبب وراء وجود مطورين كثُر أو قلائل. تمثل صعوبة بناء المشروع عائقًا كبيرًا أمام أي مطور مُحتَمل في المشاريع مفتوحة المصدر. وجود اعتماديات في مشاريع ++C/C يمكن أن يكون عائق قاتل، خصوصًا على Windows، حيث لا يوجد مدير حِزم. حتى أثناء بناء Zig نفسها، يجد معظم المطورين المحتملين صعوبة في التعامل مع اعتمادية LLVM. Zig (سوف) تقدم طريقة للمشاريع للاعتماد على المكتبات الأصيلة مباشرة - بدون الاعتماد على أن يحتوي مدير الحِزم على النسخ الصحيحة من الاعتماديات، وبطريقة تضمن نجاح بناء المشاريع من أول مرة بغض النظر عن النظام المستخدم والمنصة المستهدفة.
تعرض Zig استبدال نظام بناء المشاريع بلغة معقولة تستعمل واجهة برمجية تصريحية، وتوفر أيضًا مدير حِزم وبالتالي القدرة على الاعتماد على مكتبات C أخرى. القدرة على استخدام الاعتماديات تتيح تجريد الأفكار بشكل أفضل وبالتالي التوسع في نشر كود يمكن إعادة استخدامه.
البساطة
لدى ++C وRust وD العديد من المزايا، الأمر الذي قد يعجلهم مشتتين للتركيز بعيدًا عن البرنامج الفعلي الذي تعمل عليه. يجد المرء نفسه يحاول تصحيح أخطائه في اللغة نفسها بدلًا من تصحيح أخطاء البرنامج.
ليست لدى Zig أي وحدات ماكرو أو برمجة وصفية، ومع ذلك فهي قوية بما يكفي للتعبير عن برامج معقدة بطريقة واضحة خالية من الرتابة. حتى Rust تمتلك وحدات ماكرو خاصة مثل format!
، وتقوم بتطبيقها في المترجم نفسه. بينما في Zig فالوظيفة المماثلة مطبقة في المكتبة الأساسية دون الحاجة لكود مخصوص في المترجم.
الأدوات
يمكن تحميل Zig من قسم التحميل. توفر Zig أرشيفات مضغوطة لأنظمة Linux وWindows وmacOS وFreeBSD. يشرح التالي ما تحصل عليه في هذه الأرشيفات:
- تثبيت عن طريق تحميل وتفريغ ملفات دون الحاجة لإعداد النظام
- بناء ساكن يغني عن الحاجة لإعتماديات في زمن التنفيذ
- تستعمل LLVM كبنية تحتية مما يتيح عمل تحسينات عميقة ودعم لأغلب المنصات الأساسية
- ترجمة مختلطة لأغلب المنصات الأساسية
- تُشحن مع الكود المصدري لـlibc التي سيتم ترجمتها عند الحاجة لأي منصة مدعومة
- تتضمن نظام بناء ذا تخزين مؤقت
- تترجم كود بلغتي C و++C مع دعم libc