تقييم الموضوع :
  • 0 أصوات - بمعدل 0
  • 1
  • 2
  • 3
  • 4
  • 5
شرح مبسط - Lambda Expressions
#1
بسم الله الرحمن الرحيم
بمناسبة قدوم شهر رمضان اعاده الله على الجميع بكامل الخير و البركة
و جعلنا و اياكم من عتقائه من النار , و تقبل منا و منكم صالح الاعمال
احببت ان اقدم هذه المقالة المبسطة عن تعبيرات لامبدا (Lambda Expressions)

السلام عليكم و رحمة الله و بركاته
لا يخفى على الكثير من المبرمجين مدى قوة هذا الاسلوب و فاعليته في العمل البرمجي اذ انه يختصر عليك الكثير من الجهد و الوقت في كتابة الكود و يجعله اكثر قابلية للقراءة و اكثر وثوقية وقوة من قبل المترجم.
و بالعودة الى تاريخ هذا الاسلوب على ما اذكر كانت بدايته مع Java 8  , ثم جاءت #C و سرقت هذا الاسلوب او قلدته (لا يهم كثيراً , كله في مصلحتنا) , و على راي المثل السرقة من السارق ؟؟؟؟ ,جاءت Swift و سرقت من الاثنين , و اخيراً فيما قرأت جاءت لغة قوقل الجديدة Kotlin و سرقت من Swift و هكذا دواليك .


ببساطة Lambda Expressions هي دالة او اجراء بدون اسم يمكن استخدامه حيث اعتدنا استخدام Delegate 
و يمكن ان ياتي بسطر واحد او اكثر من سطر
و يمكن ان يحتوي على بارمترات (ليس كل الانواع)       

عملية انشائها سهلة و بسيطة حسب ما اعتدنا
عبر الكلمتين  Function او Sub   مثلما اعتدنا في عملنا مع الدوال او الاجراءات
بعد ذلك تاتي البارمترات
و بعدها ياتي جسم الدالة (الوظيفة المناطة بها)
ملاحظة: عندما تكون الدالة بسطر واحد لا نحتاج عندها الى (End Sub  او  End Function)
اما اذا كانت اكثر من سطر فنحتاج عندها الى الكلمات السابقة

مثال: دالة بسطر و احد مع طريقة الاستدعاء
PHP كود :
       Dim Sum1 = Function(p1
        MsgBox
(Sum1(5)) 
مثال : دالة باكثر من سطر مع الاستدعاء
PHP كود :
       Dim sum2 = Function(p)
 
                      Return 2
                   End 
Function
 
       MsgBox(sum2(5)) 
اذا دققت في الكود السابق سترى ان الدالة ليس لها اسم و هي تحتوي على بارميتر واحد بدون تحديد نوعه و بعدها وظيفة الدالة تجمع رقم مع قيمة الباراميتر


كما و يمكنك انشاء الدالة مع استدعائها بسطر واحد فقط كما يلي:
PHP كود :
       MsgBox((Function(As Integer1)(5)) 
لاحظ في الكود السابق حددنا نوع للبارميتر .

ملاحظة : لا يمكنك تحديد نوع الدالة اذا كانت من النوع الاول (ذات السطر الواحد) , بينما يمكنك ذلك مع دالة تحتوي اكثر من سطر
و المقصود بتحديد النوع هو نوع الارجاع كما يلي:
PHP كود :
       Dim sum2 = Function(p) As Integer
                       
Return 2
                   End 
Function
 
       MsgBox(sum2(5)) 


نفس الكلام ينطبق على الاجراءات او كما يحب البعض تسميتها بالروتين

مثال:
PHP كود :
       Dim ShowMsg1 Sub(SMsgBox(S)
 
       ShowMsg1("Welcome...")


 
       Dim ShowMsg2 Sub(S)
 
                          MsgBox(S)
 
                      End Sub

        ShowMsg2
("Welcome again..."


تمرير  Lambda Expression كوسيط (بارميتر) ضمن الاجراءات و الدوال التي تقبل وسائط من النوع Delegate    
لكي نفهمها اكثر ناخذ هذا المثال
PHP كود :
   Sub Test(ByVal value As IntegerByVal Fun As Func(Of IntegerBoolean))
 
       If Fun(valueThen
            MsgBox
("Success")
 
       Else
            MsgBox
("Failure")
 
       End If
 
   End Sub 
كما ترى في الاجراء السابق هناك وسيطين الاول من النوع الرقمي و الثاني عبارة عن دالة من النوع المنطقي تقبل بارميتر رقمي
اما وظيفة الدالة فهي تعيد Success في حال كانت True او  Failure في حال كانت False
اما تطبيقها فياتي وقت الاستدعاء كما يلي
PHP كود :
       Test(4, Function(numnum Mod 2 0
كما ترى تم استدعاء الدالة و تعويض الرقم , اما جسم الدالة فهو الوظيفة (الرقم تقسيم 2=0) وهي صحيحة و بالتالي ستكون النتيجة العائدة هي Success

و لاعادة النتيجة Failur يمكنك استخدامها كما يلي
PHP كود :
       Test(5, Function(numnum 10
كما ترى 5 ليس اكبر من 10 ...... و الباقي عندك.



صيغة (Lambda Expression Syntax

- Lambda Expression  ليس لها اسم
- Lambda Expression لا يمكن التصريح عنها بالطرق التالية (OverLoads ,Overrides
- Lambda Expression ذات السطر الواحد لا يمكن ان تكون لها نوع كما سبق ذكره ,بينما يمكن ان يكون لها نوع اذا كانت متعددة الاسطر.
- Lambda Expression  ذات السطر الواحد لا تحتوي على (End Function ,End Sub) , و العكس صحيح.
- Lambda Expression لا يمكنك استخدام البارمترات الاختيارية وفق الكلمة (Optional) , كما لا يمكنك استخدام  البرامترات من النوع (ParamArray) , و كذلك الانواع (Generic) .
-بالشكل العام اذا احتوت الدالة على نوع ارجاع صريح يتم التعامل معه , و الا سيتم الاستدلال على النوع من خلال القيمة العائدة اذا لم تحتوي الدالة على نوع ارجاع ,وهناك ما يعرف بالنوع المهيمن في حال كنت تتعامل مع مصفوفات تحتوي على عدة انواع من البيانات , كمثال على ذلك اذا كنت تتعامل مع مصفوفة رقمية تحتوي على ارقام عادية و عشرية فان النوع المهيمن و الذي يستوعب باقي الانواع سيكون من النوع Double كونه اكثر مرونه وقابلية للتوسع و استيعاب الارقام الاخرى.
-اذا كانت الدالة من النوع ذو السطر الواحد فيجب ان تعيد قيمة معها .


لم ينتهي الحديث هنا و مازال لدى هذا الاسلوب المتقدم الكثير من الامور الواجب عرضها و مناقشتها ... باذن الله

يتبع.....
اللهم لك الحمد كما ينبغي لجلال وجهك و عظيم سلطانك
في حل و ترحال
الرد }}}
تم الشكر بواسطة: Amir_Alzubidy , sendbad100 , sendbad100
#2
و عليكم السلام و رحمة الله
و كل عام و انتم بخير و جميع المسلمين ان شاء الله .
ما شاء الله تبارك الرحمن
يعجبني الاسلوب، و التسلسل و الفن في ايصال المعلومة.
الله يعطيك العافية و يزيدك علم و يرزقك . اللهم آمين
الرد }}}
تم الشكر بواسطة: ابو ليلى
#3
موضوع قيم ومهم
جزاك الله خير
<يعطيك العافية>
الرد }}}
تم الشكر بواسطة: ابو ليلى
#4
اشيع استخدام لتعبيرات لامدا هو تمرير الدالة كوسيط من النوع Delegate
اعرف ان الكلام غامض بعض الشيئ ؟؟ لكن اذا كنت قد تعاملت مع Delegate سابقاً يمكنك فهمها بشكل بسيط

لناخذ مثال على ذلك 
لنفرض انه طلب منا ان نقوم بمعرفة العمليات التي يتم تشغيلها و التي تمتلك Thread واحد فقط
يوجد عدد من الحلول لمثل هذا السؤال كما يلي
PHP كود :
Dim filteredQuery From proc In Diagnostics.Process.GetProcesses
                        Where proc
.Threads.Count 1
                        Select proc

    For Each proc In filteredQuery
        MsgBox
(proc.ProcessName)
Next 
كود بسيط يستخدم Linq يقوم بتحديد العملية التي توافق الشرط من المصفوفة ويضعها في Enumerable
ثم نقوم بالمرور على عناصر التعداد و نعرض اسم العملية

الان لو فكرنا قليلاً كيف يمكن ان نستفيد من Lambd في مثل هذا الامر
اولاً يمكنني الحصول على العمليات في مصفوفة من النوع Process
ومن ثم يمكنني استخدام الطرق الموسعة داخل المصفوفات و التي تحتوي على دوال جاهزة تقبل بداخلها بارمترات من النوع Lambda
عبارة Where السابقة في استعلام Linq يمكنني العثور عليها كدالة تعمل مع المصفوفات
و تحتاج الى بارميتر من النوع Func و تعيد قيمة منطقية
ليتضح الامر اكثر
PHP كود :
       Dim procList As Process() = Diagnostics.Process.GetProcesses

        Dim filteredList 
procList.Where(Function(pp.Threads.Count 1)

 
       For Each proc In filteredList
            MsgBox
(proc.ProcessName)
 
       Next 
في السطر الثاني من الكود و تحديداً الدالة Where سترى انها تطبق على المصفوفات من النوع IEnumerable(of TSource) k  و التي بدورها مشتقة من النوع Generic(of TSource) p   و تعيد النوع  IEnumerable(of TSource) p                 
لا تهتم كثيراً بهذا الكلام , و لكن دقق ان الدالة تحتاج الى وسيط من النوع Function يعيد قيمة منطقية
ولاحظ اننا مررنا دالة Lambda مع بارميتر (البارميتر هنا هو Process) و عمل الدالة هو تحديد Process يمتلك Thread واحد فقط
و بالتالي اذا تحقق الشرط ستعود الدالة بقيمة True و بالتالي ستضاف Process الى التعداد filteredList
و اخيراً قمنا بالمرور على العناصر داخل التعداد و عرض اسم العملية


بالنسبة للدوال التوسعية او الاضافية (Extention Methods) التي يمكنك جعلها تتوفر مع كائن ما بشكل افتراضي , ليس لدي الوقت الكثير لادخل في شرحها
لكن ولانني قد اشرت سابقاً لها في احد الاجوبة هنا تحديداً  يمكنك مراجعة الرابط لفهم جزئي لها

يبدو الامر فيه بعض الصعوبة مبدئياً و لكن مع الوقت و التعود على استخدامها ستكتشف مدى قوتها.



مفهوم الـ  asynchronous 
بالعربي تلفظ (اسنكرونس)  Shy  لفظها ثقيل

وعكسها synchronous (سنكرونس) متزامن
مفهوم عدم التزامن مفهوم منفصل عن هذا الموضوع و يحتاج الى شرح منفصل 
ولكن ولكي نغطي هذا الجزء مع الدوال و الاجراءات بشكل عام يمكننا شرحه بشكل مبسط وفق وروده في الاكواد

ترتبط العمليات غير المتزامنة بكلمتين مفتاحيتين هم Async  و  Await
و لجعل دالة ما او اجراء من النوع غير المتزامن يمكنك اضافة الكلمة Async قبل الدالة او الاجراء و من ثم تحتاج الى الكلمة Await في قلب الدالة, و التي بدورها تؤجل تنفيذ الكود الى ان يتم تنفيذ مهمة معينة او حتى يمكن ان تكون فاصل زمني محدد
مثال على ذلك
PHP كود :
   Private Async Sub Button1_Click(sender As ObjectAs EventArgsHandles Button1.Click
        Await ExampleMethodAsync
()
 
       TextBox1.Text "Task Completed..."
 
   End Sub

    Async 
Function ExampleMethodAsync() As Task
        Await Task
.Delay(3000)
 
   End Function 
لن يتم ملئ TextBox1 الى بعد 3 ثواني , طبعاً هذا المثال للتوضيح وهو غير مرتبط بموضوعنا هنا و ليصبح اكثر ارتباط انظر الى الكود التالي
حاول ان تضع الكود في حدث Form_Load
PHP كود :
       AddHandler Button1.Click,
 
           Async Sub(sender1e1)
 
               Await ExampleMethodAsync()
 
               TextBox1.Text vbCrLf "Task Completed..."
 
           End Sub 
هل اتضحت لك الصورة الان , ربطنا حدث Click الخاص بالزر بالاجراء ExampleMethodAsync تلقائياً مع بداية اقلاع النموذج ولم نعد بحاجة لمعالجة حدث الضغط (Click) بشكل منفصل

لم ينتهي الحديث عن Lambda و هناك الكثير الكثير عنه و يحتاج شرحه و التعمق فيه الى الكثير من الوقت و الجهد
و اتمنى ان اكون قد انرت شمعة لمن يجهل هذا الاسلوب او لمن يحتاج الى معلومات بسيطة عنه
اترك الباقي للمهتمين بالتوسع و اثراء الموضوع بمعرفتهم .

(25-05-17, 11:00 PM)Amir_alzubidy كتب : و عليكم السلام و رحمة الله
و كل عام و انتم بخير و جميع المسلمين ان شاء الله .
ما شاء الله تبارك الرحمن
يعجبني الاسلوب، و التسلسل و الفن في ايصال المعلومة.
الله يعطيك العافية و يزيدك علم و يرزقك . اللهم آمين
شكرا على دعواتك اخي امير و بارك الله فيك و زادك من نعمه
(26-05-17, 12:02 AM)Fantastico كتب : موضوع قيم ومهم
جزاك الله خير
جزاك الله بالمثل اخي الكريم
اللهم لك الحمد كما ينبغي لجلال وجهك و عظيم سلطانك
في حل و ترحال
الرد }}}
تم الشكر بواسطة: Fantastico , Amir_Alzubidy


المواضيع المحتمل أن تكون متشابهة .
الموضوع : الكاتب الردود : المشاهدات : آخر رد
Lightbulb [VB.NET] درس مبسط في الاتصال بقاعدة بيانات SQL Bin-Komet 3 3,304 23-10-17, 09:34 AM
آخر رد: مصمم هاوي
  [مقال] مفهوم Generics بشكل مبسط ابو ليلى 3 2,463 26-05-17, 12:18 AM
آخر رد: Fantastico
  معلومة ::: Regular Expressions RaggiTech 6 2,780 06-10-12, 09:06 PM
آخر رد: RaggiTech
  Lambda Expressions من جديد VB2008 RaggiTech 0 2,213 01-10-12, 05:59 PM
آخر رد: RaggiTech
  (الدرس الثالث - الجزء 1 ) = امر التكرار والدوران for ... next مبسط RaggiTech 0 2,728 01-10-12, 03:11 PM
آخر رد: RaggiTech

التنقل السريع :


يقوم بقرائة الموضوع: بالاضافة الى ( 1 ) ضيف كريم