Sunday, August 10, 2008

lambda expression in C#

C# 3.0 has many new features come from functional programming, which make C# 3.0 merging between imperative and functional language to be more powerful and elegant language.


The Functional Language consider as one of the most popular and the oldest programming paradigm [first functional language appears at 1955] has unique characteristics such as:

  • The program considered as a set of functions.
  • Functions do not change the program's status, all variables are immutable.
  • No loops, recursion only :)
  • and lambda expression.

For more information about FP => "Functional Programming on Wikipedia".

Lambda expression is unnamed function replaces anonymous method.

x => x * 2; //lambda expression


The previous statement means that x is a parameter of function, and x * 2 is the function body, we can rewrite this without lambda as the following:

int func(int x)

{

return x * 2;

}


lambda can accept more than one parameter using parentheses and commas


(x, y) => x * y ;


Can written as

int func (int x, int y)

{

return x * y;

}

To use lambda in useful way:

class Program

{

delegate int Increment2(int i); //delegate to call the function that created using lambda


static void Main(string[] args)

{

Increment2 I = x => x += 2; // assign lambda expression to delegate instance

Console.WriteLine(I(3)); // call it and return 5

}

Furthermore, to reduce the code amount we wrote, we can use the generic Func delegate.
Func delegate is a generic delegate to function can takes result type, and up to four parameters.


delegate TResult Func();

delegate TResult Func(T1 arg1);

delegate TResult Func(T1 arg1, T2 arg2);

delegate TResult Func(T1 arg1, T2 arg2, T3 arg3);

delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4);


We can rewrite previous example using Func as the following:


Func<int, int> I = x => x += 2;

Note: the last generic parameter is the result type, and it’s mandatory.
Another generic delegate already exist is Action, Action is delegate to function that does not return a value.

e.g.
static void Main (string [] args)

{

var Persons = new List {

new Person{FirstName="First",lastName="Person"},

new Person{FirstName="Second",lastName="Person"},

new Person{FirstName="Third",lastName="Person"},

new Person{FirstName="Forth",lastName="Person"},

new Person{FirstName="Fifth",lastName="Person"},

};

Action print = person => Console.WriteLine(person);

Persons.ForEach(print);

}

On another side we can use lambda expression as parameter to another method.
List Names = new List();

Names.Add("Ahmad");

Names.Add("Mohammed");

Names.Add("Joseph");

Names.Add("Adam");

string findName = "Ahmad";

string name = Names.Find(str => str == findName); //use lambda as a parameter

if (string.IsNullOrEmpty(name))

Console.WriteLine("not found");


You can replace previous lambda with anonymous method


string name = Names.Find(delegate(string str) { return str == findName; });


You must notice from previous code that the lambda can access the outer variable


Now how can we use recursion using lambda:


To write recursion code, first we shall declare delegate using Func<> and assign it with null value, and assign instance delegate to lambda expression in new statement, we most write lambda recursion in two statement to avoid “
Use of unassigned local variable” error.
e.g.
Func<int, int> factorial = null;

factorial = Num => Num == 1 ? Num : factorial(Num - 1);

lambda statement


lambda statement similar to lambda expression, but lambda statement use brackets because it‘s contains more than one statement, while lambda expression not.


Func
<string, int, string> lstatement = (Name, Num) =>

{

string tempStr = null;

for (int i = 0; i <>

{

tempStr += Name;

}

return tempStr;

};

Console.WriteLine(lstatement("Omar",5));


Notes:

  • Lambda expression can be converted to expression tree or to delegate.
  • Lambda statement can convert only to delegate type.
  • Anonymous methods must be explicitly typed their parameters, but lambda infers their types.



No comments: