ريفال

ريفال ( بالروسية : РЕФАЛ ، وتعني "لغة الخوارزميات ذات الدوال المتكررة") هي لغة برمجة وظيفية موجهة نحو الحسابات الرمزية، وتشمل معالجة النصوص ، وترجمة اللغات ، والذكاء الاصطناعي . [ 1 ] وهي من أقدم لغات هذه العائلة، حيث تم تصورها لأول مرة عام 1966 كأداة نظرية، وظهر أول تطبيق لها عام 1968. وكان الهدف من ريفال هو الجمع بين البساطة الرياضية والفعالية العملية لكتابة برامج كبيرة ومعقدة.

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

تعتمد بنية البيانات الأساسية في لغتي Lisp و Prolog على قائمة خطية تُبنى باستخدام عملية cons بشكل تسلسلي، مما يتيح الوصول إلى العنصر رقم n في القائمة في زمن O(n) . أما في Refal، فتُبنى القوائم وتُفحص من كلا الطرفين، مع إمكانية مطابقة الأنماط للقوائم المتداخلة والقائمة الرئيسية على حد سواء. في الواقع، تُعد بنية البيانات الأساسية في Refal شجرة وليست قائمة . وهذا يمنح حرية وسهولة في إنشاء هياكل البيانات باستخدام آليات تحكم بسيطة رياضياً تعتمد على مطابقة الأنماط والاستبدال.

يتضمن برنامج Refal أيضًا ميزة تسمى المجمد لدعم التقييم الجزئي الفعال .

يمكن تطبيق Refal على معالجة وتحويل هياكل الشجرة، على غرار XSLT . [ 2 ]

الأساسيات

يُعرض أدناه مثال لبرنامج " مرحباً بالعالم" من Refal .

$ENTRY Go { = <Hello>;} مرحبًا { = <Prout 'Hello world'>; }

يتضمن البرنامج أعلاه دالتين باسم Go و Hello. تُكتب الدالة باسمها متبوعًا بجسمها بين قوسين معقوفين. تُحدد الدالة Go كنقطة دخول البرنامج باستخدام التوجيه $ENTRY.

يمكن اعتبار التعبيرات الموجودة في أجسام الدوال بمثابة "استدعاءات" للدوال في بنية شبيهة بلغة ليسب . على سبيل المثال، يبدو أن الدالة Hello تستدعي الدالة Prout المدمجة مع السلسلة النصية 'Hello world' كوسيط. ومع ذلك، فإن معنى الاستدعاء وآليته مختلفان تمامًا. لتوضيح هذا الاختلاف، لننظر إلى الدالة التالية التي تحدد ما إذا كانت سلسلة نصية متناظرة (palindrome ).

Pal { = صحيح؛ s.1 = صحيح؛ s.1 e.2 s.1 = <Pal e.2>; e.1 = خطأ؛ }

يوضح هذا المثال دالةً ذات بنية أكثر تعقيدًا، تتألف من أربع جمل (عبارات). تبدأ كل جملة بنمط متبوع بعلامة يساوي، ثم عبارة عامة على الجانب الأيمن. وتنتهي الجملة بفاصلة منقوطة. على سبيل المثال، نمط الجملة الثانية من الدالة هو "s.1" والعبارة هي "True".

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

تُنفَّذ الدالة بمقارنة وسيطها مع أنماط الجمل بالترتيب الذي تظهر به في تعريفها، حتى يتم العثور على أول نمط مطابق. ثم تستبدل الدالة الوسيط بالتعبير الموجود على الجانب الأيمن من الجملة المطابقة.

إذا تضمنت نتيجة تطبيق دالة تعبيرًا فرعيًا بين قوسين زاويين (كما سيحدث بعد تطبيق الجملة الثالثة من مثالنا)، فإن Refal تعالج النتيجة باستدعاء الدالة المحددة بالرمز الأول بين القوسين. ويتوقف التنفيذ عندما لا تحتوي النتيجة على المزيد من الأقواس الزاوية لتوسيعها بهذه الطريقة.

يمكن قراءة الدالة Pal بشكل غير رسمي على النحو التالي: "إذا كان التعبير فارغًا، فاستبدله بـ True. وإذا كان التعبير رمزًا واحدًا، فاستبدله بـ True. وإذا كان التعبير رمزًا متبوعًا بتعبير عشوائي e.2 متبوعًا بنفس الرمز، فاستبدله بالتعبير <Pal e.2>. (بمعنى آخر، تجاهل الرمزين المتطابقين في البداية والنهاية واستدعِ الدالة بشكل متكرر). وإلا، فاستبدل التعبير بـ False. (النمط e.1 يتطابق دائمًا)."

فيما يلي ثلاثة مسارات تنفيذ خطوة بخطوة، مع شرح بأرقام الجمل المطبقة في كل خطوة لإنتاج الخطوة التالية.

<Pal 'noon'> (#3) <Pal 'oo'> (#3) <Pal> (#1) حقيقي
<Pal 'wow'> (#3) <Pal 'o'> (#2) حقيقي
<Pal 'revolver'> (#3) <Pal 'evolve'> (#3) <Pal 'volv'> (#3) <Pal 'ol'> (#4) خطأ شنيع

يمكننا الآن أن نرى أن مثال "Hello World" يتم تنفيذه في الواقع كسلسلة من تحويلات التعبير التالية:

 قم بتهيئة الجهاز بالتعبير الأولي المحدد بـ $ENTRY: <انطلق> (طبّق الجملة في Go) <مرحباً> (طبّق الجملة في "مرحباً") <Prout 'Hello world'> (Prout هو برنامج مدمج يقوم بطباعة وتوسيع النص إلى لا شيء) (لا يوجد ما ينطبق؛ توقف)

أمثلة أخرى

مضروب

حقيقة { 0 = 1؛ sN = <* sN <Fact <- sN 1>>>; }

هنا، يتطابق الصفر مع الرقم وينتج 1. على أي رمز آخر يمثل رقمًا، اضربه بنتيجة (Fact (- sN 1)) لاحظ أسلوب البادئة للمعاملات.

حساب المضروب باستخدام الحلقات

حقيقة { sn = <حلقة sn 1>; }; حلقة { 0 sf = sf; sn sf = <Loop <- sn 1> <* sn sf>>; }

كما هو واضح، يعمل sn كعداد للحلقة.

المساواة

متساوي { (e.1)(e.1) = T; (هـ.1)(هـ.2) = F; }

تُعرَّف الدالة هنا على النحو التالي: إذا تم إعطاء مصطلحين، وكان المصطلحان متطابقين، فإن الشرط الأول يتطابق وينتج القيمة "صحيح". وإلا فإن الشرط الثاني يتطابق وينتج القيمة "خطأ".

من الخصائص المهمة للغة Refal أن جميع الدوال فيها ذات وسيط واحد. (لكن يمكن تحليلها إلى حدود في تعبير كما هو موضح أعلاه).

لو

يُعد تحديد هياكل التحكم أمرًا سهلاً

لو { T ثم (e.1) وإلا (e.2) = e.1؛ F ثم (e.1) وإلا (e.2) = e.2؛ }

هنا يتم تقييم e1 فقط عندما يتطابق التعبير المدخل مع 'True' ثم e1 وإلا e2 نفس الشيء بالنسبة لـ e2.

قم بضغط الفراغات

اضغط { e.1'__'e.2 = <Squeeze e.1'_'e.2>; e.1 = e.1; }

(استخدام '_' بدلاً من المسافة لتوضيح استدعاء الدالة.) يتطابق الشرط الأول عندما تصادف الدالة Squeeze مسافتين متتاليتين في تعبير الإدخال، وتستبدلهما بمسافة واحدة. أما الشرط الثاني فيتطابق فقط عندما لا يتطابق الشرط الأول، ويعيد القيمة الناتجة وهي التعبير الحالي.

الضغط باستخدام التكرار الصريح

اضغط { '__'e.1 = <Squeeze '_'e.1>; sA e.1 = sA <Squeeze e.1>; = ; };

مراجع

  1. تورتشين، فالنتين ف. (1989). "مقدمة إلى ريفال" . دليل برمجة ريفال-5 ودليل مرجعي . هوليوك: شركة نيو إنجلاند للنشر. مؤرشف من الأصل في 3 يوليو 2008. تم الاطلاع عليه في 5 أبريل 2010 .
  2. "ريفال: لغة معالجة مستندات XML" . مؤرشف من الأصل بتاريخ 2007-12-06 . تم الاطلاع عليه بتاريخ 2008-03-18 .