el Guille, la Web del Visual Basic, C#, .NET y más...

Novedades de Visual Basic 9.0

(Parte 7 de 9)

 
Publicado el 22/Jul/2007
Actualizado el 24/Jul/2007
Autor: Guillermo 'guille' Som

Novedades de Visual Basic 9.0 (Parte 7 de 9): Expresiones lambda. Árboles de expresiones.



 

Expresiones lambda

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; };

 

Árboles de expresiones

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)


Código de ejemplo (comprimido):

Para bajarte el código, hazlo desde la página principal de
Las Novedades de Visual Basic 9.0 con la CTP de Junio 2007.


 


La fecha/hora en el servidor es: 23/12/2024 18:14:18

La fecha actual GMT (UTC) es: 

©Guillermo 'guille' Som, 1996-2024