En inglés: Lambda expressions. También llamadas "funciones en
línea". Para abreviar, las expresiones lambda son como eso, funciones en
línea, es decir, podemos definir una función donde se espera una expresión
cualquiera, y el valor que esa "función" devuelve es lo que se usará como
expresión.
Según la documentación de Visual Studio 2008 (recuerda que todavía no es
ni la beta 2), una expresión lambda es:
Una expresión lambda es una función sin nombre que calcula y
devuelve un solo valor. Las expresiones lambda se pueden utilizar
dondequiera que un tipo del delegado sea válido.
Para definir una expresión lambda, usaremos la instrucción Function a la
que le indicaremos los parámetros que recibirá y como "cuerpo" de la función
solo tendrá el cálculo de una expresión en la que se "manejarán" esos
parámetros (como mínimo debe haber un parámetro), y el tipo de datos de esa
función es del mismo tipo que el valor "calculado".
Por ejemplo, si queremos calcular el área de un circulo (para que sea un
ejemplo parecido al que publicó Octavio Hernández en
uno de sus artículos en la sección de
Firmas invitadas
(ahora te te pondré un par de links a sus artículos sobre LINQ en C#),
tendríamos que escribir algo como esto:
Dim area = Function(ByVal radius As Double) Math.PI * radius * radius
Para usar la variable area, la usaremos como con cualquier delegado:
Console.WriteLine("El área de un círculo de radio 5 es " & area(5))
Si quieres saber más sobre las expresiones lambda, te recomiendo que te
leas este artículo de Octavio Hernández, (aunque te advierto que es con C#):
Las
expresiones lambda en C# 3.0.
Si quieres "fardar" (o por lo menos defenderte cuando te digan que en C# las
expresiones lambda son más potentes), decirte que el código que te he
mostrado antes para la definición de la variable area, en C# no se puede
hacer así de simple, ya que hay que indicar que se usará un delegado generic
llamado Func, y la forma de hacerlo sería esta:
Func<double, double> area = (radius) => Math.PI * radius * radius;
Y que en Visual Basic también podríamos escribir de esta forma:
Dim area1 As Func(Of Double, Double) = Function(ByVal r As Double) Math.PI * r + r
Pero "supongo" que gracias a la "relajación total" de delegados, pues...
se puede "inferir" el tipo de esa expresión lambda.
En cualquier caso, todo esto de las expresiones lambda (y los árboles de
expresiones) es "por culpa" de LINQ, ya que LINQ lo utiliza para sus
expresiones de consultas. Por ejemplo, el uso de la cláusula Where en una
"consulta de LINQ" que escribiríamos de esta forma:
Dim nums1 = From n In numeros Where n > 3 Select n
Lo podríamos escribir así:
Dim nums2 = numeros.Where(Function(ByVal n As Integer) n > 3)
Que es en realidad lo que hará el compilador cuando se encuentre con el
código "de la expresión de consulta" anterior.
Según dicen, en la versión final no será necesario indicar si el
parámetro de la función es ByVal, más que nada para que
resulte más corto.
Algo que no tendrá Visual Basic 9.0 es la posibilidad de crear funciones
completas, es decir, poder indicar más de una instrucción en la definición
de la expresión lambda, algo que C# 3.0 si que puede hacer, por ejemplo:
Func<int, int> valor = (n) => { int i = n * n; return i + n; };
En inglés: Expression trees. Para simplificar, un árbol de
expresiones es una representación de los datos de una expresión lambda.
Cuando se evalúa una expresión lambda, el compilador genera esas
instrucciones como un árbol de expresiones.
Creo que lo mejor es que te leas el artículo de Octavio Hernández publicó
sobre
Los árboles de expresiones en C# 3.0.
Aunque seguramente sea complicado de asimilar, aquí tienes la versión
para Visual Basic de uno de los ejemplos del artículo de Octavio.
Primero te muestro el código (adaptado a la CTP de Jun 2007) en C# y después
el de Visual Basic:
El código de C#:
using System.Linq.Expressions;
namespace cs3_arboles_expresiones
{
class Program
{
static ParameterExpression px = Expression.Parameter(typeof(double), "x");
static ParameterExpression py = Expression.Parameter(typeof(double), "y");
static ParameterExpression[] parms = { px, py };
static Expression<Func<double, double, double>> hypotenuseExpr2 =
Expression.Lambda<Func<double, double, double>>(
Expression.Call(
typeof(Math).GetMethod("Sqrt"),
new Expression[] {
Expression.Add(
Expression.Multiply(px, px),
Expression.Multiply(py, py))
}),
parms);
static void Main(string[] args)
{
Console.WriteLine(hypotenuseExpr2);
// prints '(x, y) => Sqrt(Add(Multiply(x, x), Multiply(y, y)))'
Func<double, double, double> hypo = hypotenuseExpr2.Compile();
Console.WriteLine("Hypotenuse(3, 4) = " + hypo(3, 4));
Console.ReadKey();
}
}
}
El código de Visual Basic:
Imports System.Linq.Expressions
Module Module1
Dim px As ParameterExpression = Expression.Parameter(GetType(Double), "x")
Dim py As ParameterExpression = Expression.Parameter(GetType(Double), "y")
Dim parms As ParameterExpression() = {px, py}
Dim hypotenuseExpr2 As Expression(Of Func(Of Double, Double, Double)) = _
Expression.Lambda(Of Func(Of Double, Double, Double)) _
(Expression.Call(GetType(Math).GetMethod("Sqrt"), _
New Expression() _
{Expression.Add( _
Expression.Multiply(px, px), _
Expression.Multiply(py, py) _
) _
} _
), _
parms _
)
Sub Main()
' Muestra la expresión lambda al estilo de C#
Console.WriteLine(hypotenuseExpr2)
Console.WriteLine("{0}Debe mostrar:{0}(x, y) => Sqrt(x * x + y * y){0}", vbCrLf)
Dim hypo As Func(Of Double, Double, Double) = hypotenuseExpr2.Compile()
Console.WriteLine("Hypotenuse(3, 4) = " & hypo(3, 4))
Console.WriteLine("Creando la Expresión lambda directamente:")
Dim hipotenusaExpr = _
Function(ByVal x As Double, ByVal y As Double) _
Math.Sqrt(x * x + y * y)
Console.WriteLine("Hipotenusa(3, 4) = {0}", hipotenusaExpr(3, 4))
Console.ReadKey()
End Sub
End Module
Ir al índice de las
novedades de Visual Basic 2008 (VB 9.0)