لغة البرمجة الديناميكية

لغة البرمجة الديناميكية هي نوع من لغات البرمجة التي تسمح بتحديد وتنفيذ عمليات متنوعة أثناء تشغيل البرنامج، وهذا يختلف عن مرحلة الترجمة. تُتخذ القرارات الرئيسية المتعلقة بالمتغيرات واستدعاءات الدوال وأنواع البيانات أثناء تشغيل البرنامج، على عكس اللغات الثابتة حيث تكون البنية والأنواع ثابتة أثناء الترجمة. توفر اللغات الديناميكية مرونةً كبيرة، مما يسمح للمطورين بكتابة شفرة برمجية أكثر قابلية للتكيف وأكثر إيجازًا.

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

تطبيق

التقييم

تُوفر بعض اللغات الديناميكية دالة eval . تأخذ هذه الدالة سلسلة نصية أو شجرة بناء جملة مجردة تحتوي على شيفرة مكتوبة باللغة، ثم تُنفذها. إذا كانت هذه الشيفرة تُمثل تعبيرًا، تُعاد القيمة الناتجة. يُميز إريك ماير وبيتر درايتون بين توليد الشيفرة أثناء التشغيل الذي تُوفره دالة eval والتحميل الديناميكي الذي تُوفره المكتبات المشتركة ، ويُحذران من أن دالة eval تُستخدم في كثير من الحالات فقط لتنفيذ الدوال ذات الرتبة العليا (عن طريق تمرير الدوال كسلاسل نصية) أو لفك التسلسل . [ 1 ]

تغيير الكائن أثناء التشغيل

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

استنتاج النوع

بما أن العديد من اللغات الديناميكية تأتي بنظام أنواع ديناميكي، فإن استنتاج الأنواع أثناء التشغيل بناءً على القيم للتفسير الداخلي يُعد مهمة شائعة. ونظرًا لأن أنواع القيم قد تتغير أثناء عملية التفسير، فإنه يُستخدم بانتظام عند تنفيذ العمليات الذرية.

تخصيص الذاكرة المتغير

تتطلب لغات البرمجة الثابتة (ربما بشكل غير مباشر) من المطورين تحديد حجم الذاكرة المستخدمة قبل الترجمة (إلا في حال استخدام منطق المؤشرات). وبما يتوافق مع تعديل وقت تشغيل الكائنات، تحتاج اللغات الديناميكية ضمنيًا إلى (إعادة) تخصيص الذاكرة بناءً على عمليات البرنامج الفردية.

انعكاس

تُعدّ البرمجة الانعكاسية (الانعكاس) شائعة في العديد من اللغات الديناميكية، وتتضمن عادةً تحليل أنواع البيانات العامة أو متعددة الأشكال وبياناتها الوصفية . ومع ذلك، يمكن أن تشمل أيضًا التقييم الكامل وتعديل كود البرنامج كبيانات، كما هو الحال في الميزات التي توفرها لغة ليسب في تحليل تعابير S.

وحدات الماكرو

توفر بعض لغات البرمجة الديناميكية ميزات تجمع بين فحص الكود (القدرة على فحص الأصناف والدوال والكلمات المفتاحية لمعرفة ماهيتها ووظائفها ومعرفتها) والتقييم في ميزة تُسمى وحدات الماكرو . معظم المبرمجين اليوم الذين يعرفون مصطلح "ماكرو" قد صادفوه في لغتي C أو C++ ، حيث يُعدّ ميزة ثابتة مُدمجة في جزء صغير من اللغة، وتقتصر وظيفتها على استبدال السلاسل النصية في نص البرنامج. أما في اللغات الديناميكية، فتتيح وحدات الماكرو الوصول إلى آليات عمل المُصرّف، والوصول الكامل إلى المُفسّر أو الآلة الافتراضية أو بيئة التشغيل، مما يسمح بتعريف بنيات شبيهة باللغة تُحسّن الكود أو تُعدّل بناء الجملة أو قواعد اللغة.

لا تندرج لغات التجميع ، ولغة C ، ولغة C++ ، ولغة جافا المبكرة ، ولغة فورتران عمومًا ضمن هذه الفئة.

تُعتبر لغة ليسب (مكارثي، 1965) أقدم لغة برمجة ديناميكية، والتي استمرت في التأثير على تصميم لغات البرمجة حتى يومنا هذا. [ 2 ]

مثال على التعليمات البرمجية

توضح الأمثلة التالية الميزات الديناميكية باستخدام لغة Common Lisp ونظام كائنات Common Lisp (CLOS).

حساب التعليمات البرمجية في وقت التشغيل والربط المتأخر

يوضح المثال كيف يمكن تعديل دالة أثناء وقت التشغيل من خلال شفرة المصدر المحسوبة

يتم تخزين الكود المصدري كبيانات في متغير CL-USER > ( defparameter *best-guess-formula* ' ( lambda ( x ) ( * x x 2.5 ))) *BEST-GUESS-FORMULA*يتم إنشاء دالة من الكود وتجميعها أثناء التشغيل، وتكون الدالة متاحة تحت اسم best-guess CL-USER > ( compile 'best-guess *best-guess-formula* ) # <Function 15 40600152F4>يمكن استدعاء الدالة CL-USER > ( أفضل تخمين 10.3 ) 265.225قد يتم تحسين الكود المصدري أثناء التشغيل CL-USER > ( setf *best-guess-formula* ` ( lambda ( x ) , ( list 'sqrt ( third *best-guess-formula* )))) ( LAMBDA ( X ) ( SQRT ( * X X 2.5 )))يتم الآن تجميع نسخة جديدة من الدالة CL-USER > ( compile 'best-guess *best-guess-formula* ) # <Function 16 406000085C>سيستدعي الاستدعاء التالي الدالة الجديدة، وهي ميزة من ميزات الربط المتأخر CL-USER > ( أفضل تخمين 10.3 ) 16.28573

تغيير الكائن أثناء التشغيل

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

; فئة شخص. للشخص اسم. CL-USER > ( defclass person () (( name :initarg :name ))) # <STANDARD-CLASS PERSON 4020081FB3>; طريقة طباعة مخصصة لكائنات فئة person CL-USER > ( defmethod print-object (( p person ) stream ) ( print-unreadable-object ( p stream :type t ) ( format stream "~a" ( slot-value p 'name )))) # <STANDARD-METHOD PRINT-OBJECT NIL ( PERSON T ) 4020066E5B>مثال واحد: CL-USER > ( setf *person-1* ( make-instance 'person :name "Eva Luator" )) # <PERSON Eva Luator>يحصل الشخص من الفئة على خانة ثانية. ثم يحتوي على اسم الخانة وعمرها. CL-USER > ( defclass person () (( name :initarg :name ) ( age :initarg :age :initform :unknown ))) # <STANDARD-CLASS PERSON 4220333E23>تحديث طريقة طباعة الكائن CL-USER > ( defmethod print-object (( p person ) stream ) ( print-unreadable-object ( p stream :type t ) ( format stream "~a age: ~" ( slot-value p 'name ) ( slot-value p 'age )))) # <STANDARD-METHOD PRINT-OBJECT NIL ( PERSON T ) 402022ADE3>لقد تغير الكائن الحالي الآن، حيث أصبح لديه خانة إضافية وطريقة طباعة جديدة. CL-USER > *person-1* # <PERSON Eva Luator age: UNKNOWN>يمكننا تعيين خانة العمر الجديدة للمثيل CL-USER > ( setf ( slot-value *person-1* 'age ) 25 ) 25تم تحديث الكائن CL-USER > *person-1* # <PERSON Eva Luator age: 25>

تجميع التعليمات البرمجية في وقت التشغيل بناءً على فئة المثيلات

في المثال التالي، تحصل الفئة "person" على فئة أساسية جديدة. يُعاد تعريف دالة الطباعة بحيث تجمع عدة دوال في دالة واحدة فعّالة. تُجمّع الدالة الفعّالة بناءً على فئة الوسيط والدوال المتاحة والقابلة للتطبيق في وقت التشغيل.

; فئة الشخص CL-USER > ( defclass person () (( name :initarg :name ))) # <STANDARD-CLASS PERSON 4220333E23>; يقوم شخص ما بطباعة اسمه فقط CL-USER > ( defmethod print-object (( p person ) stream ) ( print-unreadable-object ( p stream :type t ) ( format stream "~a" ( slot-value p 'name )))) # <STANDARD-METHOD PRINT-OBJECT NIL ( PERSON T ) 40200605AB>; نسخة شخصية CL-USER > ( defparameter *person-1* ( make-instance 'person :name "Eva Luator" )) *PERSON-1*عرض بيانات شخص CL-USER > *person-1* # <PERSON Eva Luator>; الآن نعيد تعريف دالة الطباعة لتكون قابلة للتوسيع ؛ تقوم دالة around بإنشاء سياق لدالة الطباعة وتستدعي الدالة التالية CL-USER > ( defmethod print-object :around (( p person ) stream ) ( print-unreadable-object ( p stream :type t ) ( call-next-method ))) # <STANDARD-METHOD PRINT -OBJECT ( :AROUND ) ( PERSON T ) 4020263743>; تقوم الطريقة الأساسية بطباعة الاسم CL-USER > ( defmethod print-object (( p person ) stream ) ( format stream "~a" ( slot-value p 'name ))) # <STANDARD-METHOD PRINT-OBJECT NIL ( PERSON T ) 40202646BB>; فئة جديدة باسم id-mixin توفر معرف CL-USER > ( defclass id-mixin () (( id :initarg :id ))) # <STANDARD-CLASS ID-MIXIN 422034A7AB>تقوم دالة الطباعة بطباعة قيمة خانة المعرّف CL-USER > ( defmethod print-object :after (( object id-mixin ) stream ) ( format stream " ID: ~a" ( slot-value object 'id ))) # <STANDARD-METHOD PRINT-OBJECT ( :AFTER ) ( ID-MIXIN T ) 4020278E33>الآن نعيد تعريف فئة الشخص لتشمل المزيج id-mixin CL-USER > ( defclass person ( id-mixin ) (( name :initarg :name ))) # <STANDARD-CLASS PERSON 4220333E23>; يحتوي الكائن الحالي *person-1* الآن على خانة جديدة، وقد قمنا بتعيينها إلى 42 CL-USER > ( setf ( slot-value *person-1* 'id ) 42 ) 42; لعرض الكائن مرة أخرى. تحتوي دالة طباعة الكائن الآن على طريقة فعّالة، تستدعي ثلاث طرق: طريقة حول، والطريقة الأساسية، وطريقة ما بعد. CL-USER > *person-1* # <PERSON Eva Luator ID: 42>

أمثلة

تشمل لغات البرمجة الديناميكية الشائعة جافا سكريبت ، وبايثون ، وروبي ، وبي إتش بي ، ولوا ، وبيرل . وتُعتبر اللغات التالية لغات ديناميكية بشكل عام:

انظر أيضاً

مراجع

  1. ماير، إريك وبيتر درايتون (2005)، الكتابة الثابتة حيثما أمكن، والكتابة الديناميكية عند الحاجة: نهاية الحرب الباردة بين لغات البرمجة (ملف PDF) ، شركة مايكروسوفت ، CiteSeerX 10.1.1.69.5966 
  2. هاربر، روبرت (2016). الأسس العملية للغات البرمجة . نيويورك: مطبعة جامعة كامبريدج. ص 195. ISBN  9-781107-150300.
  3. الفصل 24. دعم اللغة الديناميكية . Static.springsource.org. تم الاطلاع عليه بتاريخ 17-07-2013.
  4. "Groovy - Home" . مؤرشف من الأصل بتاريخ 2014-03-02 . تم الاطلاع عليه بتاريخ 2014-03-02 .

للمزيد من القراءة

(يستخدم الكثيرون مصطلح "لغات البرمجة النصية".)