أوجه انتباهكم إلى ترجمة تقرير ألكساندر كوزمينكو (منذ أبريل من هذا العام وهو يعمل رسميًا كمطور لمترجم Haxe) حول التغييرات في لغة Haxe التي حدثت منذ إصدار Haxe 3.4.

لقد مر أكثر من عامين ونصف على إصدار Haxe 3.4. خلال هذا الوقت ، تم إصدار 7 إصدارات تصحيح ، 5 إصدارات معاينة لمرشحي الإصدار Haxe 4 و 2 من Haxe 4. لقد كان الطريق طويلًا إلى الإصدار الجديد وهو جاهز تقريبًا (لا يزال هناك حوالي 20 مشكلة يتعين حلها).

شكر ألكساندر مجتمع Haxe على الإبلاغ عن الأخطاء ، لرغبتهم في المشاركة في تطوير اللغة. بفضل مشروع تطور haxe ، ستظهر أشياء مثل ما يلي في Haxe 4:
- العلامات المضمنة
- وظائف مضمنة في موقع الاتصال
- وظائف السهم

أيضًا ، في إطار هذا المشروع ، تجري مناقشات حول ابتكارات محتملة مثل: الوعود ، وتعدد الأشكال ، والأنواع الافتراضية (معلمات النوع الافتراضي).
بعد ذلك ، تحدث ألكساندر عن التغييرات في صيغة اللغة .

الأول هو بناء الجملة الجديد لوصف بناء جملة أنواع الوظائف. بناء الجملة القديم كان غريبا بعض الشيء.
Haxe هي لغة برمجة متعددة النماذج ، وكانت دائمًا تدعم وظائف من الدرجة الأولى ، لكن بناء الجملة لوصف أنواع الوظائف قد ورث من لغة وظيفية (ويختلف عن تلك المعتمدة في النماذج الأخرى). ويتوقع المبرمجون على دراية البرمجة الوظيفية وظائف مع بناء الجملة هذا لدعم الكاري التلقائي. لكن في Haxe هذا ليس كذلك.
يتمثل العيب الرئيسي في بناء الجملة القديم ، وفقًا لـ Alexander ، في عدم القدرة على تحديد أسماء الوسائط ، ولهذا السبب يجب عليك كتابة تعليقات تعليقات توضيحية طويلة مع وصف للوسائط.
لكن لدينا الآن صيغة جديدة لوصف أنواع الوظائف (والتي ، بالمناسبة ، تمت إضافتها إلى اللغة كجزء من مبادرة تطور haxe) ، حيث توجد مثل هذه الفرصة (على الرغم من أن هذه الفرصة اختيارية ، ولكنها موصى بها). بناء الجملة الجديد أسهل في القراءة ويمكن اعتباره جزءًا من وثائق الكود.
عيب آخر في بناء الجملة القديم لوصف أنواع الوظائف هو عدم Void->Void
- الحاجة إلى تحديد نوع وسائط الدالة حتى عندما لا تقبل الدالة أي وسيطات: Void->Void
(هذه الدالة لا تأخذ أي وسيطات ولا تعيد أي شيء).
في الصيغة الجديدة ، يتم تطبيق هذا بشكل أكثر أناقة: ()->Void

والثاني هو وظائف السهم أو تعبيرات لامدا - نموذج قصير لوصف وظائف مجهولة. لطالما طلب المجتمع إضافتهم إلى اللغة ، وأخيراً حدث ذلك!
في مثل هذه الوظائف ، بدلاً من الكلمة الرئيسية المرتجعة ، يتم استخدام تسلسل الأحرف ->
(ومن هنا يكون اسم بناء الجملة "وظيفة السهم").
في الصيغة الجديدة ، يظل من الممكن ضبط أنواع الوسائط (لأن نظام الاستدلال التلقائي للنوع لا يمكنه دائمًا القيام بذلك بالطريقة التي يريدها المبرمج ، على سبيل المثال ، يمكن للمترجم أن يقرر استخدام Float
بدلاً من Int
).
القيد الوحيد في بناء الجملة الجديد هو عدم القدرة على تعيين نوع الإرجاع بشكل صريح. إذا لزم الأمر ، عندئذٍ يمكنك اختيار استخدام بناء الجملة القديم أو استخدام بناء جملة نوع التحقق في نص الدالة ، والذي سيُعلم المترجم بنوع الإرجاع.

لا تملك وظائف السهم تمثيلًا خاصًا في شجرة بناء الجملة ؛ حيث تتم معالجتها بنفس طريقة وظائف المجهول العادية. يتم استبدال التسلسل ->
بكلمة return
.

أصبح التغيير الثالث - final
الآن كلمة أساسية (في Haxe 3 final
كان أحد العلامات الوصفية المضمنة في المحول البرمجي).
إذا قمت بتطبيقه على الفصل ، فسيحظر الميراث منه ، وينطبق الشيء نفسه على الواجهات. تطبيق التصفيات final
على طريقة الفصل سيمنعه من تجاوزه في الفصول الفرعية.
ومع ذلك ، في Haxe ، كانت هناك طريقة للالتفاف على القيود المفروضة بواسطة الكلمة الأساسية final
- يمكنك استخدام علامة @:hack
meta tag لهذا (ولكن لا يزال ، يجب القيام بذلك فقط إذا لزم الأمر).

التغيير الرابع هو وسيلة لإعلان الحقول الاختيارية في بنيات مجهولة. في السابق ، تم استخدام علامة meta @:optional
لهذا ، فقط أضف علامة استفهام أمام اسم الحقل.

خامسًا ، أصبحت التعدادات المجردة عضوًا كاملًا في عائلة نوع Haxe ، وبدلاً من علامة meta @:enum
تُستخدم الكلمة الأساسية @:enum
الآن للإعلان عنها.

تغيير مماثل أثر على علامة meta @:extern
.

السابع هو بناء جملة تقاطع نوع جديد يعكس بشكل أفضل جوهر الهياكل المتوسعة.
يتم استخدام نفس بناء الجملة الجديد للحد من قيود معلمات الكتابة ؛ فهو ينقل بدقة أكثر القيود المفروضة على نوع ما. بالنسبة إلى شخص غير مألوف لدى Haxe ، يمكن اعتبار بناء الجملة القديم MyClass<T:(Type1, Type2)>
متطلبًا لأن يكون نوع المعلمة T
إما Type1
أو Type2
. يخبرنا بناء الجملة الجديد بشكل صريح أن T
يجب أن يكون كلاهما Type1
و Type2
في نفس الوقت.

الثامن هو القدرة على استخدام []
للإعلان عن حاوية Map
فارغة (ومع ذلك ، إذا لم تحدد نوع المتغير بشكل صريح ، فسيقوم المحول البرمجي بإخراج النوع كصفيف لهذه الحالة).
بعد الحديث عن التغييرات في بناء الجملة ، دعنا ننتقل إلى وصف وظائف جديدة في اللغة .
لنبدأ بالتكرارات الجديدة ذات القيمة الأساسية

تمت إضافة بناء جملة جديد لاستخدامه.
لدعم هذه التكرارات ، يجب أن يقوم النوع إما بتطبيق طريقة keyValueIterator():KeyValueIterator<K, V>
أو أساليب hasNext():Bool
و next():{key:K, value:V}
. في الوقت نفسه ، يعد KeyValueIterator<K, V>
مرادفًا لمكرر منتظم في البنية المجهولة Iterator<{key:K, value:V}>
.
يتم تطبيق برامج التكرار ذات القيمة الأساسية لبعض الأنواع من مكتبة DynamicAccess
القياسية ( String
، Map
، DynamicAccess
) ، والعمل جارٍ أيضًا لتنفيذها على المصفوفات.

بالنسبة للسلاسل ، يتم استخدام فهرس الأحرف في السلسلة كمفتاح ، ويتم استخدام رمز الحرف في الفهرس المحدد كقيمة (إذا كان الحرف نفسه مطلوبًا ، فيمكن استخدام أسلوب String.fromCharCode()
).
بالنسبة لحاوية Map
، تعمل أداة التكرار الجديدة مثل طريقة التكرار القديمة ، أي أنها تستقبل مجموعة من المفاتيح في الحاوية وتمريرها ، حيث تطلب قيمًا لكل مفتاح.
بالنسبة إلى DynamicAccess
(برنامج التفاف لكائنات مجهولة) ، يعمل التكرار باستخدام الانعكاس (للحصول على قائمة بحقول كائن باستخدام طريقة Reflect.fields()
على قيم الحقول بأسمائهم باستخدام طريقة Reflect.field()
).

يستخدم Haxe 4 مترجم الماكرو الجديد تمامًا ، "eval". وصفها سايمون كرايجسكي ، مؤلف المترجم الشفهي ، بشيء من التفصيل في مدونة Haxe الرسمية ، وكذلك في تقريره المرحلي عن العام الماضي .
التغييرات الرئيسية في عمل المترجم:
- أسرع عدة مرات من مترجم الماكرو القديم (4 مرات في المتوسط)
- يدعم التصحيح التفاعلي (سابقًا ، لوحدات الماكرو ، يمكن استخدام إخراج وحدة التحكم فقط)
- يتم استخدامه لتشغيل المترجم في وضع المترجم (سابقًا تم استخدام neko لهذا. بالمناسبة ، يفوق eval أيضًا neko في السرعة).

يعد دعم يونيكود لجميع المنصات (باستثناء نيكو) أحد أكبر التغييرات في Haxe 4. تحدث سايمون عن ذلك بالتفصيل في العام الماضي . ولكن فيما يلي نظرة عامة مختصرة عن الحالة الحالية لدعم سلسلة Unicode في Haxe:
- من أجل Lua و PHP و Python و eval (مترجم الماكرو) ، يتم تنفيذ دعم يونيكود الكامل (ترميز UTF8)
- بالنسبة إلى الأنظمة الأساسية الأخرى (JavaScript و C # و Java و Flash و HashLink و C ++) ، يتم استخدام ترميز UTF16.
وبالتالي ، تعمل الخطوط الموجودة في Haxe بالطريقة نفسها للأحرف المضمنة في المستوى الرئيسي متعدد اللغات ، ولكن بالنسبة للأحرف خارج هذه المستوى (على سبيل المثال ، الرموز التعبيرية) ، يمكن أن ينتج عن رمز العمل مع الخطوط نتائج مختلفة وفقًا للنظام الأساسي (ولكن هذا لا يزال أفضل ، من الوضع الذي لدينا في Haxe 3 ، عندما كان لكل منصة سلوكها الخاص).

بالنسبة للسلاسل المشفرة بواسطة Unicode (في كلا UTF8 و UTF16) ، تمت إضافة برامج تكرارية خاصة إلى مكتبة Haxe القياسية التي تعمل على قدم المساواة على جميع الأنظمة الأساسية لجميع الشخصيات (داخل المستوى الرئيسي متعدد اللغات وما بعده):
haxe.iterators.StringIteratorUnicode haxe.iterators.StringKeyValueIteratorUnicode

نظرًا لحقيقة أن تنفيذ السلاسل يختلف من منصة إلى أخرى ، فمن الضروري أن تضع في الاعتبار بعض الفروق الدقيقة في عملها. في UTF16 ، يستغرق كل حرف وحدتي بايت ، لذا فإن الوصول إلى حرف في سلسلة حسب الفهرس سريع ، ولكن فقط داخل المستوى الرئيسي متعدد اللغات. من ناحية أخرى ، في UTF8 ، يتم دعم جميع الأحرف ، ولكن يتم تحقيق ذلك على حساب البحث البطيء عن حرف في سلسلة (حيث يمكن أن تشغل الأحرف أرقامًا مختلفة من البايتات في الذاكرة ، يتطلب الوصول إلى حرف عن طريق الفهرس التكرار عبر السطر في كل مرة من البداية). لذلك ، عند العمل باستخدام سلاسل كبيرة في Lua و PHP ، عليك أن تضع في اعتبارك أن الوصول إلى شخصية تعسفية يعمل ببطء شديد (أيضًا على هذه الأنظمة الأساسية ، يتم حساب طول السلسلة مرة أخرى في كل مرة).
ومع ذلك ، على الرغم من الإعلان عن دعم Unicode الكامل لـ Python ، لا ينطبق هذا التقييد عليه لأن الخطوط الموجودة به يتم تنفيذها بطريقة مختلفة قليلاً: بالنسبة للأحرف داخل المستوى الرئيسي متعدد اللغات ، تستخدم ترميز UTF16 ، وللحروف الأوسع (3 و المزيد من وحدات البايت) يستخدم بايثون UTF32.
يتم تنفيذ تحسينات إضافية لمترجم الماكرو eval: السلسلة "يعرف" ما إذا كان يحتوي على أحرف Unicode. في حالة عدم احتوائها على مثل هذه الأحرف ، يتم تفسير السلسلة على أنها تتكون من أحرف ASCII (حيث يأخذ كل حرف 1 بايت). يتم أيضًا تحسين الوصول التسلسلي حسب الفهرس في eval: يتم تخزين موضع آخر حرف تم الوصول إليه في السطر. لذلك إذا انتقلت أولاً إلى الحرف العاشر في السلسلة ، فعندما تنتقل بعد ذلك إلى الحرف العشرين ، سيبحث eval عنها ليس من بداية السطر الأول ، ولكن يبدأ من الحرف العاشر. بالإضافة إلى ذلك ، يتم تخزين طول السلسلة في eval مؤقتًا ، أي ، يتم حسابه فقط عند الطلب الأول.

يقدم Haxe 4 دعمًا لمساحات الأسماء الخاصة بعلامات الترجمة ، والتي قد تكون مفيدة ، على سبيل المثال ، لتنظيم التعليمات البرمجية عند كتابة مكتبات مخصصة.
أيضًا ، ظهرت مساحة اسم محجوزة لأعلام الترجمة - target
، والذي يستخدمه المترجم لوصف النظام الأساسي الهدف وسلوكه:
target.name
- اسم النظام الأساسي (js ، cpp ، php ، وما إلى ذلك)- يقول
target.utf16
- أنه يتم تنفيذ دعم Unicode باستخدام UTF16 target.sys
- يشير إلى ما إذا كانت الفئات من حزمة sys متاحة (على سبيل المثال ، للعمل مع نظام الملفات)target.static
- يشير إلى ما إذا كان النظام الأساسي ثابتًا (في الأنظمة الأساسية الثابتة ، لا يمكن أن تكون الأنواع الأساسية Int
و Float
و Bool
null
من القيمة)target.threaded
- يشير إلى ما إذا كان النظام الأساسي يدعم تعدد العمليات

وبالمثل ، ظهر دعم مساحة الاسم لعلامات التعريف. لا توجد حتى الآن مساحات محجوزة لعلامات التعريف في اللغة ، ولكن قد يتغير الموقف في المستقبل.

ReadOnlyArray
إضافة نوع ReadOnlyArray
إلى مكتبة Haxe القياسية - وهي عبارة عن تجريد على صفيف عادي ، حيث تتوفر الطرق فقط لقراءة البيانات من الصفيف.

ابتكار آخر في اللغة هو الحقول النهائية والمتغيرات المحلية.
إذا final
استخدام final
بدلاً من الكلمة الأساسية var
عند الإعلان عن حقل فئة أو متغير محلي ، فهذا يعني أنه لا يمكن إعادة تعيين الحقل أو المتغير المعين (إذا حاول المترجم القيام بذلك ، فسوف يلقي خطأً). ولكن في الوقت نفسه ، يمكن تغيير حالته ، وبالتالي فإن الحقل أو المتغير النهائي ليس ثابتًا.

يجب تهيئة قيم الحقول النهائية إما عند التصريح عنها ، أو في المنشئ ، وإلا فإن المترجم سوف يلقي خطأ.

HashLink هي عبارة عن منصة جديدة مع الجهاز الظاهري الخاص بها ، تم إنشاؤه خصيصا لهاكس. يدعم HashLink ما يسمى بـ "التحويل البرمجي المزدوج" - يمكن تجميع الشفرة إما في bytecode (وهو سريع جدًا ، يسرع من عملية تصحيح الأخطاء للتطبيقات المتقدمة) ، أو في رمز C (والذي يتميز بزيادة الأداء). خصص نيكولاس HashLink للعديد من منشورات مدونة Haxe وتحدث عنه أيضًا في مؤتمر سياتل العام الماضي . تستخدم تقنية HashLink في الألعاب الشائعة مثل Dead Cells و Northgard.

ميزة أخرى مثيرة للاهتمام في Haxe 4 هي Null safety ، التي لا تزال في المرحلة التجريبية (بسبب الايجابيات الخاطئة وعدم كفاية فحوصات أمان الكود)
ما هو الأمن لاغية؟ إذا لم تعلن وظيفتك بشكل صريح أنها يمكن أن تقبل قيمة null
باعتبارها قيم معلمات ، فعندما تحاول تمريرها null
، فإن المترجم سوف يرمي الخطأ المقابل. بالإضافة إلى ذلك ، بالنسبة لمعلمات الوظائف التي يمكن أن تكون null
كقيمة ، سيتطلب منك المحول البرمجي كتابة تعليمات برمجية إضافية للتحقق من هذه الحالات ومعالجتها.
يتم تعطيل هذه الوظيفة بشكل افتراضي ، لكنها لا تؤثر على سرعة تنفيذ التعليمات البرمجية (إذا قمت بتمكينها مع ذلك) ، حيث يتم إجراء الاختبارات الموصوفة فقط في مرحلة الترجمة. يمكن تمكينه لكافة التعليمات البرمجية ، بالإضافة إلى تمكينه تدريجيًا للحقول والفئات والحزم الفردية (وبالتالي توفير انتقال تدريجي إلى رمز أكثر أمانًا). يمكنك استخدام علامات التعريف الخاصة ووحدات الماكرو لهذا الغرض.
الأوضاع التي يمكن أن تعمل فيها Null-security هي: Strict
(الأكثر صرامة) ، Loose
(الوضع الافتراضي) Off
(تستخدم لتعطيل عمليات التحقق من الحزم والأنواع الفردية).

للوظيفة المعروضة على الشريحة ، يتم تمكين التحقق من الأمان Null. نرى أن هذه الوظيفة تحتوي على معلمة اختيارية ، أي يمكننا تمريرها كقيمة معلمة. عند محاولة ترجمة التعليمات البرمجية باستخدام هذه الوظيفة ، سينتج عن برنامج التحويل البرمجي عدد من الأخطاء:
- عند محاولة الوصول إلى حقل ما من الكائنات (لأنه قد يكون
null
) - عند محاولة تعيين str str ، والتي ، كما نرى ، لا يجب أن تكون
null
(وإلا ، كان يجب أن نعلنها ليس String
، بل أنها Null<String>
) - عند محاولة إرجاع كائن
s
من دالة (حيث يجب ألا ترجع الدالة null
)
كيفية إصلاح هذه الأخطاء؟

نحتاج فقط إلى إضافة التدقيق null
إلى الكود (داخل الكتلة مع التدقيق null
، يعرف المترجم أنه لا يمكن أن تكون null
ويمكن استخدامها بأمان معها) ، وتأكد أيضًا من أن الوظيفة لا تُرجع null
!

بالإضافة إلى ذلك ، عند إجراء اختبارات الأمان Null ، يأخذ المترجم في الاعتبار الترتيب الذي يتم به تنفيذ البرامج. على سبيل المثال ، إذا بعد التحقق من قيمة المعلمة s
للإلغاء لإنهاء الوظيفة (أو رمي استثناء) ، فإن المترجم "سيعرف" أنه بعد هذا التحقق ، لم تعد المعلمة s
null
، وأنه يمكن استخدامها بأمان.

إذا كان المحول البرمجي يمكّن الوضع الصارم لفحوصات الأمان Null ، فسيتطلب ذلك إجراء فحوصات إضافية ل null
في الحالات التي يكون فيها بين الفحص الأولي لقيمة null
ومحاولة للوصول إلى حقل الكائن الذي تم تنفيذ أي رمز يمكنه تعيينه على null
.

في الوضع "فضفاض" (يُستخدم بشكل افتراضي) ، لن يتطلب المحول البرمجي مثل هذه الاختبارات (بالمناسبة ، يتم استخدام هذا السلوك أيضًا بشكل افتراضي في TypeScript).

أيضًا ، عند تشغيل اختبارات الأمان Null ، يتحقق المحول البرمجي من تهيئة الحقول الموجودة في الفئات (مباشرة عند الإعلان عنها أو في المُنشئ). وإلا ، فسيقوم برنامج التحويل البرمجي برمي الأخطاء عند محاولة تمرير كائن من هذه الفئة ، وكذلك عند محاولة استدعاء أساليب على هذه الكائنات ، حتى يتم تهيئة جميع حقول الكائن. يمكن إيقاف تشغيل هذه الاختبارات للحقول الفردية من الفصل بوضع علامة عليها باستخدام العلامة الوصفية @:nullSafety(Off)
تحدث ألكساندر أكثر عن الأمن Null في Haxe في أكتوبر الماضي .

قدم Haxe 4 القدرة على إنشاء فصول ES6 لجافا سكريبت ، وتم تمكينه باستخدام علامة js-es=6
.

توفر وظائف التضمين في مكان المكالمة (تضمين موقع الاتصال) المزيد من الخيارات للتحكم في التوازن بين أداء الرمز والحجم. تُستخدم هذه الوظيفة أيضًا في مكتبة Haxe القياسية.
ما هي تحب؟ يسمح لك بتضمين نص الدالة (باستخدام inline
) فقط في تلك الأماكن التي يُطلب فيها ضمان الأداء العالي (على سبيل المثال ، إذا لزم الأمر ، استدعاء طريقة ضخمة بما فيه الكفاية في الحلقة) ، بينما لا يتم تضمين نص الدالة في أماكن أخرى. نتيجة لذلك ، سيتم زيادة حجم الرمز الذي تم إنشاؤه زيادة طفيفة.

الاستخدام التلقائي (الامتدادات التلقائية للأنواع) يعني أنه بالنسبة للأنواع ، يمكنك الآن تعريف الامتدادات الثابتة في مكان إعلان النوع. هذا يلغي الحاجة إلى استخدام بناء using type;
كل مرة using type;
في كل وحدة نمطية حيث يتم استخدام أساليب الكتابة والامتداد. في الوقت الحالي ، يتم تطبيق هذا النوع من الامتدادات فقط لعمليات النقل ، ولكن في الإصدار النهائي (وفي الإنشاءات الليلية) ، يمكن استخدامه ليس فقط لعمليات النقل.

في Haxe 4 ، سيكون من الممكن إعادة تعريف عامل التشغيل للوصول إلى حقول كائن لأنواع الملخص (فقط للحقول غير الموجودة في الكتابة). للقيام بذلك ، استخدم الطرق المحددة بعلامة meta @:op(ab)
.

العلامات المدمجة هي ميزة تجريبية أخرى في Haxe. لا تتم معالجة رمز الترميز المدمج من قبل المترجم كمستند xml - يرى المترجم أنه سلسلة مُلفوفة في علامة meta @:markup
. .

-, - @:markup
, .

( untyped
). . , , Js.build()
- @:markup
, <js>
, js-.

Haxe 4 - - , — .

. , . , Int
, , C.

— .
:

JVM- JDK, Java-. . .

, async
/ await
yield
. ( C#, ). Haxe github.

Haxe , . ( ) . , .

API . , , API .
Haxe 4 !