Fexpr

في لغات برمجة ليسب ، تُعرف الدالة fexpr بأنها دالة تُمرر إليها معاملاتها دون تقييمها. عند استدعاء fexpr، يُقيّم جسم الدالة فقط؛ ولا تُجرى أي تقييمات أخرى إلا إذا تم استدعاؤها صراحةً من قِبل fexpr. في المقابل، عند استدعاء دالة ليسب عادية، تُقيّم المعاملات تلقائيًا، وتُمرر نتائج هذه التقييمات فقط إلى الدالة؛ وعند استدعاء ماكرو ليسب (التقليدي) ، تُمرر المعاملات دون تقييم، ولكن تُقيّم النتيجة التي تُرجعها دالة الماكرو تلقائيًا.

أصل اسم "fexpr"

في بدايات لغة ليسب، كانت بيئة البرمجة تربط كل رمز بقائمة ارتباط ، بدلاً من ربطه مباشرةً بقيمة. [ 1 ] تضمنت المفاتيح القياسية لهذه القوائم مفتاحين يُستخدمان لتخزين قيمة بيانات، يتم البحث عنها عند ظهور الرمز كوسيط ( APVAL و APVAL1 )؛ وأربعة مفاتيح تُستخدم لتخزين دالة، يتم البحث عنها عند ظهور الرمز كمعامل. من بين مفاتيح الدوال، يشير SUBR إلى دالة عادية مُجمَّعة، يتم تقييم معاملاتها وتمريرها إليها؛ ويشير FSUBR إلى دالة خاصة مُجمَّعة، يتم تمرير معاملاتها دون تقييم؛ ويشير EXPR إلى دالة عادية مُعرَّفة من قِبل المستخدم؛ ويشير FEXPR إلى دالة خاصة مُعرَّفة من قِبل المستخدم. الفرق الوحيد بين FEXPR و EXPR هو ما إذا كانت المعاملات تُقيَّم تلقائيًا أم لا.

في الاستخدام الأصلي الدقيق، تُعرَّف الدالة FEXPR بأنها دالة معرفة من قِبل المستخدم تُمرَّر معاملاتها دون تقييم. مع ذلك، في الاستخدامات اللاحقة، قد يصف مصطلح fexpr أي دالة من الدرجة الأولى تُمرَّر معاملاتها دون تقييم، بغض النظر عما إذا كانت الدالة بدائية أم معرفة من قِبل المستخدم. [ 2 ]

مفتاحالمتاجرمُعرَّف بواسطةالوظيفة/الشكل الخاص
تقييمقيمة البيانات
APVAL1قيمة البيانات
فرعيوظيفةنظاموظيفة
FSUBRوظيفةنظامشكل خاص
EXPRوظيفةمستخدموظيفة
FEXPRوظيفةمستخدمشكل خاص

مثال

كمثال بسيط على كيفية عمل تعبيرات fexpr، إليك تعريف تعبير fexpr مكتوب بلغة برمجة Kernel ، وهي مشابهة للغة Scheme . (بحسب الاصطلاح في Kernel، تبدأ أسماء تعبيرات fexpr دائمًا بالرمز $ ).

( $define! $f ( $vau ( x y z ) e ( $if ( >=? ( eval x e ) 0 ) ( eval y e ) ( eval z e ))))

يُقدّم هذا التعريف تعبيرًا برمجيًا يُسمى $f ، يأخذ ثلاثة مُعاملات. عند استدعاء التعبير البرمجي، يتم إنشاء بيئة محلية بتوسيع البيئة الثابتة التي تم تعريف التعبير البرمجي فيها. ثم يتم إنشاء روابط محلية: تُربط الرموز x و y و z بالمُعاملات الثلاثة لاستدعاء التعبير البرمجي، بينما يُربط الرمز e بالبيئة الديناميكية التي يتم استدعاء التعبير البرمجي منها. بعد ذلك، يتم تقييم جسم التعبير البرمجي، ($if ... ) ، في هذه البيئة المحلية، وتُصبح نتيجة هذا التقييم هي نتيجة استدعاء التعبير البرمجي. والنتيجة النهائية هي أنه يتم تقييم المُعامل الأول في البيئة الديناميكية، وبناءً على ما إذا كانت نتيجة هذا التقييم غير سالبة، يتم تقييم إما المُعامل الثاني أو الثالث وإرجاع نتيجته. أما المُعامل الآخر، سواء كان الثالث أو الثاني، فلا يتم تقييمه. 

هذا المثال ذو نطاق ثابت : البيئة المحلية هي امتداد للبيئة الثابتة. قبل عام 1980 تقريبًا، كانت لغات Lisp التي تدعم fexprs ذات نطاق ديناميكي في الغالب: كانت البيئة المحلية امتدادًا للبيئة الديناميكية، وليست امتدادًا للبيئة الثابتة. [ 3 ] ومع ذلك، كان من الضروري أحيانًا توفير اسم محلي للبيئة الديناميكية، لتجنب التقاط أسماء المعلمات المحلية. [ 4 ]

الاستخدام السائد والإهمال

استمر دعم Fexpr في لغة Lisp 1.5 ، وهي آخر لهجة قياسية جوهرية من لغة Lisp قبل أن تنقسم إلى لغات متعددة. [ 5 ] في سبعينيات القرن العشرين، دعمت لغتا Lisp السائدتان [ 6 ] - وهما MacLisp و Interlisp - كلتيهما Fexpr. [ 7 ]

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

توفر وحدات الماكرو آلية مناسبة لتحديد تعريفات الأشكال الخاصة، بينما لا توفرها وحدات FEXPR . ... يُقترح، عند تصميم لهجات لغة ليسب المستقبلية، إيلاء اهتمام جاد لاقتراح حذف وحدات FEXPR من اللغة تمامًا. [ 8 ]

منذ انحسار لغتي ماك ليسب وإنترليسب، وهما اللغتان اللتان هيمنتا على لغة ليسب بحلول عام ١٩٩٣ [ ٩ ] - وهما سكيم وكومون ليسب - لم تعد تدعم التعبيرات الوظيفية (fexprs). تدعم لغة نيو ليسب التعبيرات الوظيفية، لكنها تسميها "ماكرو". في لغة بيكو ليسب، جميع الدوال المدمجة هي تعبيرات وظيفية (fsubrs) ، بينما دوال مستوى ليسب هي تعبيرات وظيفية (exprs)، أو تعبيرات وظيفية (fexprs)، أو تعبيرات وظيفية (lexprs) ، أو مزيج منها.

Fexprs منذ عام 1980

بدءًا من لغة 3-Lisp التي ابتكرها برايان سميث عام 1982، تم تطوير العديد من لهجات لغة Lisp التجريبية لاستكشاف حدود الانعكاس الحسابي . ولدعم الانعكاس، تدعم هذه اللغات إجراءات قادرة على تجسيد هياكل بيانات متنوعة مرتبطة باستدعائها ، بما في ذلك المعاملات غير المُقَيَّمة للاستدعاء، مما يجعل هذه الإجراءات تعبيرات fexprs. وبحلول أواخر التسعينيات، ارتبطت تعبيرات fexprs بشكل أساسي بالانعكاس الحسابي. [ 10 ]

تم التوصل إلى بعض النتائج النظرية المتعلقة بتعبيرات fexprs. ففي عام 1993، استخدم جون سي. ميتشل لغة ليسب مع تعبيرات fexprs كمثال على لغة برمجة لا يمكن أن تكون تعبيراتها المصدرية مجردة رسميًا (لأن البنية النحوية الملموسة للتعبير المصدري يمكن استخلاصها دائمًا من سياق يكون فيه مُعاملًا لتعبير fexpr). [ 11 ] وفي عام 1998، بيّن ميتشل واند أن إضافة جهاز fexpr إلى حساب لامدا - وهو جهاز يمنع إعادة كتابة المعاملات - يُنتج نظامًا رسميًا بنظرية معادلات بسيطة ، مما يجعل من المستحيل إجراء تحسينات من المصدر إلى المصدر دون تحليل البرنامج بأكمله . [ 10 ] وفي عام 2007، اقترح جون إن. شوت امتدادًا لحساب لامدا يُنمذج تعبيرات fexprs دون منع إعادة كتابة المعاملات، مما قد يتجنب نتيجة واند. [ 12 ]

انظر أيضاً

اللغات التالية تُطبّق fexprs أو ما يُعادلها تقريبًا:

  • توفر لغة البرمجة ECL نوع المعلمة ("bind-class") UNEVAL، والذي يحدد أنه سيتم ربط شجرة بناء الجملة لتعبير الوسيطة بالمعلمة.
  • في io ، يمكن استخدام أساليب (كتل) الاستبطان، وذلك callبالإشارة إلى الاستدعاء بأكمله ومعالجته. انظر خانات call و self في io .
  • يستخدم Kernel$vau لإنشاء fexprs، على غرار كيفية lambdaإنشاء الدوال في Scheme .
  • يستخدم newLISPdefine-macro لتعريف fexprs. انظر القسم "وحدات ماكرو Fexpr ووحدات ماكرو إعادة الكتابة" .
  • في لغة بيكو ليسب ، (de foo X ...)يُعرّف fexpr fooالذي عند استدعائه يرتبط Xبقائمة تعابير الوسائط غير المُقيّمة. انظر التقييم في بيكو ليسب .
  • ترتبط معلمات R عمومًا بالوعود (مما يؤدي إلى التقييم الكسول )، واستدعاء substitute(param)المعلمة ينتج عنه تعبير الوسيط، انظر الاستبدالات في R.
  • في لغة REBOL ، يجب على المُستدعي وضع تعابير الوسائط التي لا تُقيّم داخل كتلة (أقواس مربعة). بعبارة أخرى، لا يمكنك تعريف دالة مستدعاة تمنع تقييم الوسائط. راجع هذه المقالة للاطلاع على أمثلة. من هذا المنطلق، لا تحتوي REBOL على تعابير fexpr، بل تُسهّل فقط محاكاة بعض استخداماتها. في لغة تدعم تعابير fexpr الحقيقية، تبدو استدعاءات fexpr كاستدعاءات دوال عادية. أما في REBOL، فتختلف الاستدعاءات التي لا تُقيّم وسائطها دائمًا عن استدعاءات الدوال العادية.

الحواشي

  1. McCarthy et al., Lisp I Programmer's Manual , pp. 88 91.
  2. بيتمان، دليل ماك ليسب المنقح ، ص 75.
  3. ستيل وغابرييل، "تطور لغة ليسب"،الصفحات 239-240 .
  4. بيتمان، دليل ماك ليسب المنقح ، ص 62
  5. ستيل وغابرييل، "تطور لغة ليسب"، الصفحات 231-232.
  6. ستيل وغابرييل، "تطور لغة ليسب"، ص 235.
  7. بيتمان، دليل ماك ليسب المنقح ، ص 182.
  8. بيتمان، "الأشكال الخاصة في لغة ليسب"، ص 179.
  9. ستيل وغابرييل، "تطور لغة ليسب"،الصفحات 245-248
  10. 1 2 واند، "نظرية التعبيرات تافهة"، ص 189.
  11. ميتشل، "حول التجريد والقوة التعبيرية للغات البرمجة"، القسم 7.
  12. شوت، "حسابات فاو ونظرية التعبيرات الوظيفية".

مراجع