الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

Lambda Expression

بدأه محمد سامر أبو سلو في 7 ديسمبر 2007 · 3 رد · 2,684 مشاهدة · في Microsoft Visual Basic.NET
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

الـ Lambda Expression هو وظيفة Function بدون اسم تحتسب وتعيد قيمة وحيدة كما يمكن استخدامها في التعابير التي تطلب إجراءات مفوضة Delegate والمثال التالي عن هذه التعابير يأخذ قيمة ويعيد الناتج بعد إضافة واحد لها

Function (num As Integer) num + 1

كما يمكنك إسناد هذه الوظيفة لمتغير وتمرير القيمة له

Dim add1 = Function(num As Integer) num + 1
Console.WriteLine(add1(5))

كما يمكنك تعريف وتنفيذ الوظيفة بنفس الوقت

Console.WriteLine((Function(num As Integer) num + 1)(5))

كما يمكن أن تستخدم Lambda Expressions كقيمة معادة عند استدعاء وظيفة أو تمريرها كوسيط لإجراء مفوض ففي المثال التالي تستخدم Lambda Expressions بوليانية كوسائط للإجراء testResult حيث تطبق الطريقة فحص بولياني لوسيط من النوع Integer ويظهر القيمة Success إذا كانت قيمة Lambda Expression هي True أو Failure إن كانت قيمته False

Module Module2

	Sub Main()
		' The following line will print Success, because 4 is even.
		testResult(4, Function(num) num Mod 2 = 0)
		' The following line will print Failure, because 5 is not > 10.
		testResult(5, Function(num) num > 10)
	End Sub

	' Sub testResult takes two arguments, an integer value and a 
	' Boolean function. 
	' If the function returns True for the integer argument, Success
	' is displayed.
	' If the function returns False for the integer argument, Failure
	' is displayed.
	Sub testResult(ByVal value As Integer, ByVal fun As Func(Of Integer, Boolean))
		If fun(value) Then
			Console.WriteLine("Success")
		Else
			Console.WriteLine("Failure")
		End If
	End Sub

End Module

وتكون صيغتها على الشكل

• هذه التعابير لا تملك اسما

• لا يمكن استخدام المعدلات معها مثل Overloads أو Overrides

• لا تستخدم قسم AS لتحديد نوع القيمة المعادة وبدلا عن ذلك يكون نوع القيمة المعادة هو نوع القيمة التي يشكلها جسم الإجراء فإن كان جسم الإجراء مثلا Cust.City = "London" فتكون القيمة المعادة بوليانية

• جسم الإجراء يجب أن يكون تعبير وليس تصريح ويمكن أن يحتوي على استدعاء لوظيفة Function ولكنه لا يمكن أن يستدعي إجراء Sub

• لا يوجد تعبير Return وتكون القيمة المعادة هي قيمة ذلك التعبير الذي يشكل جسم الوظيفة

• لا يوجد تعبير End

• يجب أن تكون جميع الوسائط محددة النوع أو تكون جميعها بأنواع بالإشارة

• غير مسموح بالوسائط الاختيارية

• الوسائط Generic غير مسموح بها

ونتيجة لهذه القواعد سنرى أن أي تعبير Lambda Expression سيكون بسيطا وغير معقد

تشترك Lambda Expression مع الوظائف Methods بأنها محددة ولها جميع حقوق الوصول كأي كود مكتوب في الطريقة التي تحتويها وهذا يتضمن الوصول إلى متغيرات الأعضاء والوظائف وجميع المغيرات الموجودة في الوظيفة التي تحتوي التعبير Lambda Expression ففي المثال التالي المتغير target هو محلي بالنسبة لـ makeTheGame والطريقة التي تم تحديد التعبير Lambda Expression فيها هي playTheGame لاحظ أن القيمة المعادة من التعبير Lambda Expression يتم تعيينها لـ takeAGuess في Main مازالت تستطيع الوصول للمتغير المحلي target

Module Module1

	Sub Main()
		' Variable takeAGuess is a Boolean function. It stores the target
		' number that is set in makeTheGame.
		Dim takeAGuess As gameDelegate = makeTheGame()

		' Set up the loop to play the game.
		Dim guess As Integer
		Dim gameOver = False
		While Not gameOver
			guess = CInt(InputBox("Enter a number between 1 and 10 (0 to quit)", "Guessing Game", "0"))
			' A guess of 0 means you want to give up.
			If guess = 0 Then
				gameOver = True
			Else
				' Tests your guess and announces whether you are correct. Method takeAGuess
				' is called multiple times with different guesses. The target value is not 
				' accessible from Main and is not passed in.
				gameOver = takeAGuess(guess)
				Console.WriteLine("Guess of " & guess & " is " & gameOver)
			End If
		End While

	End Sub

	Delegate Function gameDelegate(ByVal aGuess As Integer) As Boolean

	Public Function makeTheGame() As gameDelegate

		' Generate the target number, between 1 and 10. Notice that 
		' target is a local variable. After you return from makeTheGame,
		' it is not directly accessible.
		Randomize()
		Dim target As Integer = CInt(Int(10 * Rnd() + 1))

		' Print the answer if you want to be sure the game is not cheating
		' by changing the target at each guess.
		Console.WriteLine("(Peeking at the answer) The target is " & target)

		' The game is returned as a lambda expression. The lambda expression
		' carries with it the environment in which it was created. This 
		' environment includes the target number. Note that only the current
		' guess is a parameter to the returned lambda expression, not the target. 

		' Does the guess equal the target?
		Dim playTheGame = Function(guess As Integer) guess = target

		Return playTheGame

	End Function

End Module

ويستعرض المثال التالي مجالا عريضا من حقوق الوصول المعششة في Lambda Expression فعندما يتم تنفيذ التعبير Lambda Expression من Main كـ aDel يستخدم العناصر التالية ( حقل في الفئة aField – خاصية في الفئة aProp – وسيط للإجرائية functionWithNestedLambda هو level1 – متغير محلي لـ functionWithNestedLambda هو localVar – وسيط للتعبير Lambda Expression المعشش هو level2 )

Module Module3

	Sub Main()
		' Create an instance of the class, with 1 as the value of 
		' the property.
		Dim lambdaScopeDemoInstance = New LambdaScopeDemoClass _
			With {.Prop = 1}

		' Variable aDel will be bound to the nested lambda expression  
		' returned by the call to functionWithNestedLambda.
		' The value 2 is sent in for parameter level1.
		Dim aDel As aDelegate = _
			lambdaScopeDemoInstance.functionWithNestedLambda(2)

		' Now the returned lambda expression is called, with 4 as the 
		' value of parameter level3.
		Console.WriteLine("First value returned by aDel:   " & aDel(4))

		' Change a few values to verify that the lambda expression has 
		' access to the variables, not just their original values.
		lambdaScopeDemoInstance.aField = 20
		lambdaScopeDemoInstance.Prop = 30
		Console.WriteLine("Second value returned by aDel: " & aDel(40))
	End Sub

	Delegate Function aDelegate(ByVal delParameter As Integer) _
		As Integer

	Public Class LambdaScopeDemoClass
		Public aField As Integer = 6
		Dim aProp As Integer

		Property Prop() As Integer
			Get
				Return aProp
			End Get
			Set(ByVal value As Integer)
				aProp = value
			End Set
		End Property

		Public Function functionWithNestedLambda _
		   (ByVal level1 As Integer) As aDelegate
			Dim localVar As Integer = 5

			' When the nested lambda expression is executed the first 
			' time, as aDel from Main, the variables have these values:
			' level1 = 2
			' level2 = 3, after aLambda is called in the Return statement
			' level3 = 4, after aDel is called in Main
			' locarVar = 5
			' aField = 6
			' aProp = 1
			' The second time it is executed, two values have changed:
			' aField = 20
			' aProp = 30
			' level3 = 40
			Dim aLambda = Function(level2 As Integer) _
							  Function(level3 As Integer) _
								  level1 + level2 + level3 + localVar _
								  + aField + aProp

			' The function returns the nested lambda, with 3 as the 
			' value of parameter level2.
			Return aLambda(3)
		End Function

	End Class
End Module

كما يمكن تحويل Lambda Expressions لتتوافق مع الإجراءات المفوضة فعندما تعين Lambda Expression لإجراء مفوض Delegate يمكنك تحديد أسماء الوسائط ولكن مع إغفال أنواع البيانات الخاصة بها تاركا مهمة تحديدها للإجراء المفوض ففي المثال التالي يتم تعيين Lambda Expression لمتغير اسمه del من النوع ExampleDel الذي هو عبارة عن إجراء مفوض يأخذ وسيطتين integer و string لاحظ أن أنواع المتغيرات في Lambda Expression لم يتم تحديدها ومع ذلك فـ del يتطلب وسيطا من النوع integer ووسيطا آخر من النوع string كما تم تحديده عند تعريف ExampleDel

' Definition of function delegate ExampleDel.
Delegate Function ExampleDel(ByVal arg1 As Integer, _
							 ByVal arg2 As String) As Integer

' Declaration of del as an instance of ExampleDel, with no data 
' type specified for the parameters, m and s.
Dim del As ExampleDel = Function(m, s) m

' Valid call to del, sending in an integer and a string.
Console.WriteLine(del(7, "up"))

' Neither of these calls is valid. Function del requires an integer
' argument and a string argument.
'Console.WriteLine(del(7, 3))
'Console.WriteLine(del("abc"))

في المثال التالي يتم تحديد Lambda Expression ليعيد القيمة True إذا كان الوسيط يمتلك قسمة أو False إذا كان القيمة Nothing

Dim notNothing = Function(num? As Integer) _
			 num IsNot Nothing
Dim arg As Integer = 14
Console.WriteLine("Does the argument have an assigned value?")
Console.WriteLine(notNothing(arg))

والمثال التالي يحدد Lambda Expression يعيد Index العنصر الأخير في مصفوفة

Dim numbers() As Integer = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
Dim lastIndex = Function(intArray() As Integer) _
					intArray.Length - 1
For i = 0 To lastIndex(numbers)
	numbers(i) = numbers(i) + 1
Next

عن عائشة رضي الله عنها أن النبي صلى الله عليه وسلم قال: إن الله يحب إذا عمل أحدكم عملا أن يتقنه

نعيب زماننا والعيب فينا ... وما لزماننا عيب سوانا

ونهجو ذا الزمان بغير ذنب ... ولو نطق الزمان لنا هجانا

محمد سامر أبو سلو

#2

تكون تعابير Lambda Expressions هي الأساس لكثير من معاملات الاستعلام Linq حيث يقوم المترجم Compiler بإنشاء تعابير Lambda Expressions للقيام بالعمليات الحسابية للطرائق الخاصة بالاستعلام مثل Where و Select و Order و By و Take While فعلى سبيل المثال انظر الاستعلام التالي

Dim londonCusts = From cust In db.Customers 
				  Where cust.City = "London" 
				  Select cust

حيث ستتم ترجمته إلى الكود التالي

Dim londonCusts = db.Customers _
	.Where(Function(cust) cust.City = "London") _
	.Select(Function(cust) cust)

عن عائشة رضي الله عنها أن النبي صلى الله عليه وسلم قال: إن الله يحب إذا عمل أحدكم عملا أن يتقنه

نعيب زماننا والعيب فينا ... وما لزماننا عيب سوانا

ونهجو ذا الزمان بغير ذنب ... ولو نطق الزمان لنا هجانا

محمد سامر أبو سلو

#3

شكرا

#4

موضوع جديد مرتبط بهذا الموضوع تعابير لمدا في العمق Lambda Expressions

عن عائشة رضي الله عنها أن النبي صلى الله عليه وسلم قال: إن الله يحب إذا عمل أحدكم عملا أن يتقنه

نعيب زماننا والعيب فينا ... وما لزماننا عيب سوانا

ونهجو ذا الزمان بغير ذنب ... ولو نطق الزمان لنا هجانا

محمد سامر أبو سلو

مواضيع مشابهة