لغة البرمجة LFE

لغة إرلانج بنكهة ليسب ( LFE ) هي لغة برمجة وظيفية ، متزامنة ، ذات إدارة تلقائية للذاكرة ، ومتعددة الأغراض، وهي لهجة من لغة ليسب مبنية على إرلانج الأساسية وآلة إرلانج الافتراضية ( BEAM ). تعتمد LFE على إرلانج لتوفير بنية ليسب لكتابة تطبيقات موزعة، مقاومة للأعطال ، تعمل في الوقت الحقيقي المرن ، ومتواصلة. كما تُوسّع LFE لغة إرلانج لدعم البرمجة الوصفية باستخدام وحدات ليسب البرمجية، وتوفير تجربة تطوير محسّنة من خلال حلقة قراءة-تقييم-طباعة غنية بالميزات (REPL). [ 1 ] يتم دعم LFE بشكل فعال على جميع الإصدارات الحديثة من إرلانج؛ وأقدم إصدار مدعوم من إرلانج هو R14.

تاريخ

روبرت فيردينغ

الإصدار الأولي

بدأ العمل الأولي على LFE في عام 2007، عندما شرع روبرت فيردينغ في إنشاء نموذج أولي للغة ليسب تعمل على إرلانج. [ 2 ] ركز هذا العمل بشكل أساسي على التحليل اللغوي واستكشاف الشكل الذي قد يبدو عليه التنفيذ. لم يكن هناك نظام للتحكم في الإصدارات مستخدمًا في ذلك الوقت، لذا فإن تتبع التواريخ الأولية الدقيقة يمثل إشكالية إلى حد ما. [ 2 ]

أعلن فيردينغ عن الإصدار الأول من LFE على قائمة بريد أسئلة إرلانج في مارس 2008. [ 3 ] كان هذا الإصدار من LFE محدودًا للغاية: لم يكن يدعم letrecعمليات التكرار، أو binaryعمليات التكرار، أو عمليات التكرار receive، أو tryعمليات التكرار؛ كما أنه لم يكن يدعم واجهة سطر أوامر ليسب. [ 4 ]

تم تطوير LFE مبدئيًا باستخدام الإصدار R12B-0 من لغة إرلانج [ 5 ] على جهاز كمبيوتر محمول من نوع ديل إكس بي إس. [ 4 ]

19581960196519701975198019851990199520002005201020152020
 LISP 1، 1.5، LISP 2 (مهجورة)
 ماكليس
 تداخل
 MDL
 آلة التأتأة
 مخطط R5RS R6RS R7RS صغير
 لا شيء
 ZIL (لغة تنفيذ Zork)
 فرانز ليسب
 muLisp
 لغة الشفرة الشائعة معيار ANSI
 لي لِسْب
 مخطط معهد ماساتشوستس للتكنولوجيا
 XLISP
 تي
 شيز سكيم
 إيماكس ليسب
 أوتو ليسب
 PicoLi sp
 غامبيت
 EuLisp
 لغة ISLISP
 أوبن ليسب
 مخطط PLT مضرب
 لغة نيو ليسب
 جنو غايل
 لغة ليسب المرئية
 كلوجر
 قوس
 LFE
 هي

الدوافع

صرح روبرت فيردينج أن هناك عدة أسباب دفعته إلى بدء لغة البرمجة LFE: [ 2 ]

  • كان لديه خبرة سابقة في البرمجة بلغة ليسب.
  • نظراً لخبرته السابقة، كان مهتماً بتطبيق لغة ليسب الخاصة به.
  • على وجه الخصوص، أراد تنفيذ لغة Lisp في Erlang: لم يكن فضوليًا فقط لمعرفة كيف ستعمل وتتكامل مع Erlang، بل أراد أيضًا أن يرى كيف ستبدو .
  • منذ أن ساعد في إنشاء لغة البرمجة Erlang، كان لديه هدف يتمثل في إنشاء لغة Lisp مصممة خصيصًا للعمل على BEAM وقادرة على التفاعل بشكل كامل مع Erlang/OTP.
  • أراد تجربة ترجمة لغة أخرى على إرلانج. ولذلك، رأى في LFE وسيلة لاستكشاف ذلك من خلال توليد كور إرلانج ودمجها في الواجهة الخلفية لمترجم إرلانج.

سمات

بناء الجملة والدلالات

التعبيرات الرمزية (التعبيرات الرمزية)

مثل لغة ليسب، تُعدّ لغة LFE لغةً مُوجّهةً نحو التعبيرات . وعلى عكس لغات البرمجة غير المتجانسة ، لا تُفرّق لغات ليسب، أو تُفرّق بشكلٍ طفيف، بين التعبيرات والعبارات من الناحية النحوية : فجميع التعليمات البرمجية والبيانات تُكتب على شكل تعبيرات. وقد أدخلت LFE خاصية التجانس إلى آلة إرلانج الافتراضية.

القوائم

في لغة LFE، يُكتب نوع بيانات القائمة بحيث تُفصل عناصرها بمسافات بيضاء، وتُحاط بأقواس. على سبيل المثال، `foo` هي قائمة عناصرها هي العددان الصحيحان ` foo` و` foo`، بالإضافة إلى الذرة `[[foo| ]`. هذه القيم مُعرّفة ضمنيًا: فهي على التوالي عددان صحيحان ونوع بيانات خاص بلغة Lisp يُسمى الذرة الرمزية ، ولا يلزم تعريفها على هذا النحو.(list12'foo)12foo

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

المشغلون

تُستخدم عوامل LFE-Erlang بنفس الطريقة. التعبير

( * ( + 1 2 3 4 5 6 ) 2 )

يتم تقييمها إلى 42. على عكس الدوال في Erlang و LFE، فإن عوامل التشغيل الحسابية في Lisp متغيرة (أو n-ary )، قادرة على أخذ أي عدد من الوسائط.

تعبيرات لامدا وتعريف الدوال

يحتوي LFE على تعبيرات لامدا ، تمامًا مثل Common Lisp. ومع ذلك، فإنه يحتوي أيضًا على lambda-match لمراعاة قدرات مطابقة الأنماط في Erlang في استدعاءات الدوال المجهولة.

مصطلحات إرلانج في اللغة الإنجليزية

لا يمثل هذا القسم مقارنة كاملة بين Erlang و LFE، ولكنه يعطي فكرة عامة.

مطابقة الأنماط

إرلانج:

1 > { لين , الحالة , رسالة } = { 8 , حسنا , "تريليان" }. { 8 , حسنًا , "تريليان" } 2 > رسالة . "تريليان"

LFE:

lfe> ( set ( tuple len status msg ) #( 8 ok "Trillian" )) lfe> ;; أو باستخدام صيغة LFE الحرفية للصف: lfe> ( set `#(, len , status , msg ) #( 8 ok "Trillian" )) #( 8 ok "Trillian" ) lfe> msg "Trillian"

فهم القوائم

إرلانج:

1 > [ الجذع ( الرياضيات : الأسرى ( 3 , X )) || X <- [ 0 , 1 , 2 , 3 ]]. [ 1 , 3 , 9 , 27 ]

LFE:

lfe> ( list-comp (( <- x ' ( 0 1 2 3 ))) ( trunc ( math:pow 3 x ))) ( 1 3 9 27 )

أو أسلوب وظيفي اصطلاحي:

lfe> ( lists:map ( lambda ( x ) ( trunc ( math:pow 3 x ))) ' ( 0 1 2 3 )) ( 1 3 9 27 )

حراس

إرلانج:

right_number ( X ) when X == 42 ; X == 276709 -> true ; right_number (_) -> false .

LFE:

( defun right-number? (( x ) ( when ( orelse ( == x 42 ) ( == x 276709 ))) 'true ) (( _ ) 'false ))

الاستبعاد في رؤوس الوظائف

إرلانج:

sum ( L ) -> sum ( L , 0 ). sum ([], Total ) -> Total ; sum ([ H | T ], Total ) -> sum ( T , H + Total ).

LFE:

( مجموع ديفون ( ل ) ( مجموع ل 0 )) ( مجموع ديفون (( ' () إجمالي ) إجمالي ) ((( سلبيات h t ) إجمالي ) ( مجموع t ( + h إجمالي ))))

أو باستخدام قيمة حرفية "cons" بدلاً من صيغة المُنشئ:

( مجموع ديفون ( ل ) ( مجموع ل 0 )) ( مجموع ديفون (( ' () إجمالي ) إجمالي ) (( ` ( , h . , t ) إجمالي ) ( مجموع t ( + h إجمالي ))))

مطابقة السجلات في رؤوس الوظائف

إرلانج:

handle_info ( ping , #state { remote_pid = undefined } = State ) -> gen_server : cast ( self (), ping ), { noreply , State }; handle_info ( ping , State ) -> { noreply , State };

LFE:

( defun handle_info (( 'ping ( = ( match-state remote-pid 'undefined ) state )) ( gen_server:cast ( self ) 'ping ) `#( noreply , state )) (( 'ping state ) `#( noreply , state )))

استقبال الرسائل

إرلانج:

universal_server () -> receive { become , Func } -> Func () end .

LFE:

( defun universal-server () ( receive (( tuple 'become func ) ( funcall func ))))

أو:

( defun universal-server () ( receive ( `#( become , func ) ( funcall func ))))

أمثلة

قابلية التشغيل البيني لـ Erlang

تأخذ استدعاءات دوال إرلانج الشكل التالي : (<الوحدة النمطية>:<الدالة> <الوسيط1> ... <الوسيط>) :

( io:format "Hello, World!" )

النموذج الوظيفي

استخدام الاستدعاء الذاتي لتعريف دالة أكرمان :

( defun ackermann (( 0 n ) ( + n 1 )) (( m 0 ) ( ackermann ( - m 1 ) 1 )) (( m n ) ( ackermann ( - m 1 ) ( ackermann m ( - n 1 )))))

دوال التأليف:

( defun compose ( f g ) ( lambda ( x ) ( funcall f ( funcall g x ))))( defun check () ( let* (( sin-asin ( compose #' sin/1 #' asin/1 )) ( expected ( sin ( asin 0.5 ))) ( compose-result ( funcall sin-asin 0.5 ))) ( io:format "الإجابة المتوقعة: ~p~n" ( list expected )) ( io:format "الإجابة مع compose: ~p~n" ( list compose-result ))))

التزامن

تمرير الرسائل باستخدام "العمليات" الخفيفة الوزن في لغة إرلانج:

( defmodule messenger-back ( export ( print-result 0 ) ( send-message 2 )))( defun print-result () ( receive (( tuple pid msg ) ( io:format "تم استلام الرسالة: '~s'~n" ( list msg )) ( io:format "إرسال رسالة إلى العملية ~p ...~n" ( list pid )) ( ! pid ( tuple msg )) ( print-result ))))( defun send-message ( calling-pid msg ) ( let (( spawned-pid ( spawn 'messenger-back 'print-result ()))) ( ! spawned-pid ( tuple calling-pid msg ))))

طلبات HTTP متعددة متزامنة:

( defun parse-args ( flag ) "بالنظر إلى وسيط واحد أو أكثر من وسائط سطر الأوامر، استخرج القيم التي تم تمريرها. على سبيل المثال، إذا تم تمرير ما يلي عبر سطر الأوامر: $ erl -my-flag my-value-1 -my-flag my-value-2 ويمكن استخراجه بعد ذلك في برنامج LFE عن طريق استدعاء هذه الدالة: (let ((args (parse-args 'my-flag)))  ...  )  في هذا المثال، ستكون القيمة المُسندة إلى المتغير arg قائمةً  تحتوي على القيمتين my-value-1 و my-value-2. ( let (( `#( ok , data ) ( init:get_argument flag ))) ( lists:merge data )))( defun get-pages () "بدون وسيط، افترض أن المعامل 'url' قد تم تمريره عبر سطر الأوامر." ( let (( urls ( parse-args 'url ))) ( get-pages urls )))( defun get-pages ( urls ) "ابدأ inets وقم بإجراء (عدد كبير من) طلبات HTTP." ( inets:start ) ( plists:map ( lambda ( x ) ( get-page x )) urls ))( defun get-page ( url ) "إجراء طلب HTTP واحد." ( let* (( method 'get ) ( headers ' ()) ( request-data `#(, url , headers )) ( http-options ()) ( request-options ' ( #( sync false )))) ( httpc:request method request-data http-options request-options ) ( receive ( `#( http #(, request-id #( error , reason ))) ( io:format "Error: ~p~n" ` ( , reason ))) ( `#( http #(, request-id , result )) ( io:format "Result: ~p~n" ` ( , result ))))))

مراجع

  1. فيردينغ، روبرت. "إرلانج بنكهة اللثغة" (ملف PDF) . مصنع إرلانج . تم الاسترجاع في 17 يناير 2014 .
  2. 1 2 3 "تاريخ LFE على قائمة بريد Lisp Flavored Erlang" . تم الاسترجاع في 28-05-2014 .
  3. "إعلان LFE على قائمة بريد أسئلة إرلانج" . تم الاطلاع عليه بتاريخ 17-01-2014 .
  4. 1 2 أرمسترونغ، جو؛ فيردينغ، روبرت (30 ديسمبر 2013). "الأجهزة المستخدمة في تطوير إرلانج وLFE" (مراسلات بريد إلكتروني). مقابلة أجراها دنكان ماكجريجور . تاريخ الاسترجاع: 17 يناير 2014 .
  5. "متابعة لإعلان LFE على قائمة بريد أسئلة إرلانج" . تم الاطلاع عليه بتاريخ 17-01-2014 .