Entendiendo las Expresiones Lambda al Fin!!!

|

Con la aparición del .NET Framework 3.5 se han estado promocionando algunas de las nuevas caracteristicas de los lenguajes como por ejemplo en C# 3.0 y VB 9.0 las expresiones Lambda, la verdad la primera vez que las vi resulta que no entendi nada!! Funcionaban de un modo magico!!
Me intereso mucho entender como es que funcionan, asi es que investigando un poco resulta que no es nada magico en verdad, simplemente es un uso inteligente de algunas caracteristicas de los lenguages .NET, y voy a tratar de mostrarselos:

1. Una expresion Lambda es un metodo anonimo que puede ser usado para crear delegados o arboles de expresiones

2. Un metodo anonimo es una porcion de codigo que puede ser creada para ser usada como un delegado, a pesar de que es un metodo no es necesario declararlo, es por esto que se lo llama anonimo, esto no es nuevo viene desde C# 2.0, un link interesante para entender mejor es sobre esto es el siguiente: http://msdn.microsoft.com/msdnmag/issues/06/00/C20/default.aspx

3. Un delegado es lo que antiguamente se conocia como un puntero a una funcion, cuando necesitas pasar una funcion como un parametros es muy util, mas informacion?? Encuentrala aqui: http://msdn2.microsoft.com/en-us/library/ms173171(VS.80).aspx

4. Arbol de expresiones: quien no ha construido esto en la Universidad!! Es un tipico arbol para evaluar expresiones, claro la gente de MS lo vuelve un poco mas completo al tema y lo usa como base para cosas muy interesantes, mas informacion: http://www.interact-sw.co.uk/iangblog/2005/09/30/expressiontrees

Bien ahora que tenemos mas claros los conceptos que se usan, podemos hacer la comparacion que a mi me funciono para entenderlo correctamente:

Partiendo del concepto de que una expresion Lambda es una funcion anonima, pero con una notacion diferente, podemos entonces entender que tiene parametros de entrada y devuelve un valor, vamos bien, pero cual es la notacion correcta?? Este articulo me guio hacia la luz!!
http://www.hanselman.com/blog/TheWeeklySourceCode13FibonacciEdition.aspx

Y de ahi tomare prestado el ejemplo de las funciones para compararlos y explicarlos:

C# 2.0
static int Fibonacci (int x)
{
if (x <= 1) return 1; return Fibonacci (x-1) + Fibonacci (x-2); } C# 3.0 (Hace falta referenciar System.Core y System.Func) Func fib = null;
fib = n => n > 1 ? fib(n - 1) + fib(n - 2) : n;

Como ven estas funciones nos ayudan con la famosa serie de Fibonaccim y las 2 funcionan muy pero muy bien, claro vamos ha hacer las relaciones correspondientes para que vean que son lo mismo:

Declaracion y Parametros de entrada

C# 2.0: La tipica declaracion de la funcion en la primera linea:
static int Fibonacci (int x)

Funcion estatica llamada Fibonacci, tiene un parametro de entradad de tipo int (int en C#, Int32 para el FCL, Integer para VB) y devuelve un resultado de tipo int (lo mismo que el parentesis anterior)

C# 3.0:
Parte de la segunda linea
fib = n => n > 1 ? fib(n - 1) + fib(n - 2) : n;

Como estan pensando, solo n es la declaracion de la funcion, donde n es el parametro de entrada, pueden haber mas de un parametro de entrada, en este caso no es necesario, y se preguntaran: Y los tipos del parametro y el tipo del resultado de la funcion?? Esta es la parte interesante, aqui se usa una caracterista nueva que se llama inferencia de tipos, cuando la expresion lambda esta completa y bien escrita el compilador puede inferir los tipos que se usan, como se imaginaran entonces para que una expresion lambda funcione como nosotros deseamos debemos tener cuidado como escribimos el cuerpo de la misma, por cuanto el inferir el tipo no es tan sencillo como se piensa... Y el nombre de la funcion?? Como es un metodo anonimo no le hace falta la verdad, internamente se le asigna un nombre automaticamente para poder referenciarlo...

Cuerpo de la funcion e instrucciones

C# 2.0: lineas 2, 3, 4, 5 y 6

{
if (x <= 1) return 1; return Fibonacci (x-1) + Fibonacci (x-2); } Delimitan la funcion las llaves en la linea 2 y 6, dentro tenemos un if que verifica que el parametro no este fuera del rago y si lo esta devuelve un valor por default (1), si no hace un calculo simple basado en recursividad para ser devuelvo con una sentencia return, nada dificil verdad?? C# 3.0: Otra vez parte de la segunda linea fib = n => n > 1 ? fib(n - 1) + fib(n - 2) : n;

Muy bien aqui lo que hace es con el operador ?: (si no le conocen mucho a este operador entonces vayan a http://fcolomas.blogspot.com/2007/12/el-gourmet-net-que-es-mas-eficiente-un.html) reemplazar la funcionalidad del if y la linea del return de la funcion c# 2.0, es decir si n que es el parametro de entrada declarado antes es mayor que 1 entonces usa la recursividad para llamar de nuevo a la funcion y ejecutar un calculo simple, de lo contrario el valor que se devuelve es n.

Supongo que aun tienen preguntas, voy a aclarar algunas cosas que a mi me saltarian como dudas:

1. Que es esto de la linea 1 del la funcion en C# 3.0??
Resulta que como la expresion lambda es un metodo anonimo (puede tambien ser llamado funcion anonima) y como voy a requerir usarlo recursivamente de algun modo debo poder volver a llamarlo!! Recuerden que un metodo anonimo no tiene nombre, entonces como lo vuelvo a usar?? Justamente con el tipo Func uno puede almacenar esta referencia es por eso que se declara Func fib = null; con lo cual se reserva espacio para la referencia a la funcion, claro con esto tambien ya le damos las pistas necesarias al compilador para que luego la expresion lambda que va a ser almacenada tenga los tipos correctos tanto para los parametros como para el resultado...

2. Y el operador => que significa??
Este es la separacion de la expresion, con esta se sabe que el lado izquierdo contiene los parametros y el lado derecho las instrucciones, ahora si desean ejecutar mas instrucciones claro que se puede, al lado derecho ponen un par de llaves y dentro las instrucciones tal cual una funcion y voila!!

Esas dos son las mas notorias a mi modo de ver, ahora si ustedes tienen mas preguntas pues con todo gusto!!!

Algunos links utiles:

Expresiones Lambda para VB
http://msdn.microsoft.com/msdnmag/issues/07/09/BasicInstincts/default.aspx

Expresiones Lambda para C# desde MSDN
http://msdn2.microsoft.com/en-us/library/bb397687.aspx

1 comments:

JC said...

Excelente artículo pero puedes ponerlo para Vb .net???. Desde ya muchas Gracias

JC

jctube@gmail.com