Miguel Angel Morán

Machines take me by surprise with great frecuency...

December 2007 - Artículos

Conceptos sobre programación funcional y las mejoras sintácticas de C# 3.0 y VB 9.0

Conceptos sobre programación funcional y las mejoras sintácticas de C# 3.0 y VB 9.0

 

Hola niños ¡Estamos a unas horas del 2008! Espero que se encuentren muy bien y Santa Claus les haya traído algo más que nuevos depósitos de grasa en su puerquecito. Me quería despedir del 2007, con un artículo para toda la banda geek que pulula por la red. Deseo sinceramente que el año venidero esté lleno de Salud, Dinero y Sexo, o como dicen los cursis “Amor”. ¡No todo es computadoras niños, salgan a la calle y busquen a quien amar, puaf, escupí lengua!

En fin, al diablo con mi intento de ser gracioso. En este post podrán encontrar la mayoría de las características sintácticas nuevas que encontramos en los lenguajes de programación que salieron con la versión de Visual Studio 2008 (Me refiero a C# 3.0 Y VB 9.0) , o lo que es lo mismo en este post hablaré de los cambios sintácticos que tienen los lenguajes de programación de Microsoft para dar soporte a la tecnología denominada LINQ, además de un breviario sobre programación funcional.

Es importante conocer estos detalles toda vez que si ignoramos su funcionamiento es muy posible que no podamos explotar cabalidad la gran cantidad de características que tenemos a nuestra disposición con los lenguajes.

 

Bueno  pues ahora comencemos pues a recorrer las nuevas características que estoy seguro le serán muy interesantes.

 

 

1)  Inferencia de tipos

Una de las principales características encontramos en .NET 3.5 es la inferencia de tipos,

La inferencia de tipos es fundamental para el funcionamiento de la tecnología LINQ, toda vez que al momento de hacer un query, no es posible saber el tipo de datos  de la colección que regresará el mismo query.

Esta característica nos permite utilizar la palabra reservada var en C#  o Dim en conjunto con Option Infer On  en Visual Basic para declarar cualquier variable antes de un query o bien declararla en línea e inicializarla al mismo tiempo. Automáticamente el compilador de los lenguajes asumirá el tipo de datos asignado en la inicialización o en la ejecución del query y hará que la variable sea fuertemente tipeada durante el resto de la ejecución del programa; como podemos apreciar esto difiere totalmente el funcionamiento Javascript o del mismo Visual Basic 6.0  con su tipo de datos Variant, ya que en estos lenguajes es posible cambiar dinámicamente de tipo de datos, con su correspondiente pérdida de desempeño y la mayor probabilidad de incurrir en errores de programación en tiempo de ejecución. En .NET 3.5 esto NO se da debido a que la inferencia equipos se hace en tiempo de compilación y no en tiempo de ejecución como sucede con VB 6.0

 

Para mostrar esto comenzaremos con crear una simple clase de discos

C#

   public class Disco

    {

        public int Id;

        public string Titulo;

        public string  Interprete;

        public string Genero;

        public double Precio;

     }

 

 

VB

Public Class Disco

 

 

 Public Id As Integer

 Public Titulo As String

Public Interprete As String

Public Genero As String

Public Precio As Double

 

 

End Class

 

Posteriormente haremos uso de la inferencia de tipos de la siguiente manera

C#

 

 

var lobjDisco=new Disco() ;

            lobjDisco.Genero = "Cumbia";

            lobjDisco.Interprete = "Laura Leon";

            lobjDisco.Id = 1;

            lobjDisco.Titulo = "Noches de cumbia";

 

MessageBox.Show(lobjDisco.Genero);

 

 

VB

 

 

Option Infer On 

 

        Dim lobjDisco = New Disco

        lobjDisco.Genero = "Cumbia"

        lobjDisco.Interprete = "Laura Leon"

        lobjDisco.Id = 1

        lobjDisco.Titulo = "Noches de cumbia"

        lobjDisco.Precio = 230

 

        MsgBox(lobjDisco.Genero)

 

El código del ejemplo anterior mostrara correctamente el género del disco si somos algo curiosos podemos tratar de asignar a la variable lobjDisco un objeto que no se del tipo disco y podemos ver cómo el compilador nos dirá una grosería toda vez que la variable es fuertemente tipeada.

 

2)  Inicializadores de objetos.

Esta azúcar sintáctica es realmente útil debido a que en .NET 2.x y anteriores es necesario generar un constructor sobrecargado si queremos inicializar las variables de un objeto al momento de que es instanciado, así sí tenemos 20 variables es necesario generar 20 constructores (o muchos más si las combinamos)  para poder inicializar las propiedades o campos de nuestro objeto lo cual se traduce en una gran pérdida de tiempo al momento de estar programando. Con esta característica sin modificar el código previo de definición de la clase disco podemos utilizar la siguiente sintaxis que nos permitirá inicializar las propiedades o campos del objeto:

 

C#

  lobjDisco = new Disco { Id = 2, Genero = "Trance", Interprete = "Armin Van Buuren" , Precio=300};        

VB

lobjDisco = New Disco With {.Id = 2, .Genero = "Trance", .Interprete = "Armin Van Buuren", .Precio = 130}

 

3) Tipos anónimos

Los tipos anonimos nos permiten generar tipos al vuelo sin necesidad de declarar explícitamente la estructura y la definición de la clase. Esto se usa principalmente cuando queremos hacer algún cálculo o queremos generar un nuevo tipo basado en el resultado que nos pudiera llegar a dar un query de LINQ. En la misma manera que sucede con inferencia de tipos los tipos anónimos son creados en tiempo de compilación y no en tiempo de ejecución lo que se traduce en que no hay pérdida de rendimiento de la aplicación cabe señalar que los miembros de los tipos anónimos son de solo lectura

C#

 

            var lobjDisquera = new { Nombre = "Discos Maic" };

            var lobjDisquera2 = new { Nombre = "Discos Lucha" };

            var lobjDisquera3 = lobjDisquera2;

MessageBox.Show(lobjDisquera3.Nombre);

 

VB

 

        Dim lobjDisquera = New With {.Nombre = "Discos Maic"}

        Dim lobjDisquera2 = New With {.Nombre = "Discos Lucha"}

        Dim lobjDisquera3 = lobjDisquera2

        MsgBox(lobjDisquera3.Nombre)

 

4) Métodos de extension

Sabemos nosotros que en el mundo de. Net es possible utilizar técnicas como la herencia desde una clase abstracta y generar métodos adicionales por una clase concreta para extender la funcionalidad de una clase base, sin embargo muchas veces para lograr esto es necesario re compilar el tipo de datos original y derivado además de que es necesario tener los permisos correspondientes en la clase base para poder extender exitosamente el tipo.

Los métodos de extensión nos permiten agregar funcionalidad adicional a una clase base sin necesidad de generar subclases. Cabe señalar que los métodos de extensión deben de ser estáticos.

Para definir un método de extensión utilizamos la siguiente sintaxis

C#

 

    public static class Extensiones

    {

        public static void MostrarPrecio(this Disco pobjDisco)

        {

            MessageBox.Show(pobjDisco.Precio.ToString());

        }

 

    }

 

 

VB

 

Module Extensiones

 

    <Extension()> Public Sub MostrarPrecio(ByVal pobjDisco As Disco)

        MsgBox(pobjDisco.Precio)

    End Sub

 

End Module

 

Una vez que nosotros implementamos el código anterior podemos ver que el tipo disco ahora tienen método de extensión denominado MostrarPrecio y podemos invocarlo como cualquier otro método.

Cuando nosotros utilizamos LINQ, al momento de hacer un query, el objeto resultante de este query tiene una gran cantidad de métodos de extensión añadidos que nos permiten utilizar la funcionalidad de los operadores de query como group by, order by, count, average etc., De ahí la importancia de conocer su correcto funcionamiento.

 

5) Sintaxis de Query (LINQ)

 

LINQ como tal es una serie de tecnologías que nos permiten utilizar sentencias parecidas a SQL para manipular los objetos de la misma manera que lo hacemos con tablas del paradigma la relaciónal.

La tecnología LINQ esta dividida en diferentes sabores de acuerdo a su aplicación.

LINQ to Objects: es la tecnología que examinaremos con el siguiente código cualquier objeto que sea una colección dentro de. Net es susceptible a que se le haga un cuello con LINQ y generará a partir de ella un nuevo tipo de datos obteniendo los resultados del query

 

C#

 

            lobjDiscos.Add(new Disco{Id = 3,Genero="Pop",Interprete="Fey", Titulo="Vertigo", Precio=120});

            lobjDiscos.Add(new Disco { Id = 4, Genero = "Pop", Interprete = "Simply Red", Titulo = "Sunrise", Precio = 320 });

            lobjDiscos.Add(new Disco { Id = 5, Genero = "Rock", Interprete = "Guns n Roses", Titulo = "Use your ilution", Precio = 220 });

            lobjDiscos.Add(new Disco { Id = 6, Genero = "Dance", Interprete = "Gigi Dagostino", Titulo = "L amour tojours", Precio = 99 });

            lobjDiscos.Add(new Disco { Id = 7, Genero = "Clasica", Interprete = "Haendel", Titulo = "Mesias", Precio = 410 });

            lobjDiscos.Add(new Disco { Id = 8, Genero = "Hip Hop", Interprete = "Linkin Park", Titulo = "Meteora", Precio = 60 });

 

            var lobjDiscosSeleccionados = from lobjSeleccionDiscos in lobjDiscos

                                          where lobjSeleccionDiscos.Precio > 300

                                          orderby lobjSeleccionDiscos.Id

                                          select new {lobjSeleccionDiscos.Titulo, lobjSeleccionDiscos.Precio};

 

            foreach (var lobjDisc in lobjDiscosSeleccionados)

            {

                MessageBox.Show(lobjDisc.Titulo + " - " +lobjDisc.Precio);

           

            }

 

 

VB

 

        lobjDiscos.Add(New Disco With {.Id = 3, .Genero = "Pop", .Interprete = "Fey", .Titulo = "Vertigo", .Precio = 120})

        lobjDiscos.Add(New Disco With {.Id = 4, .Genero = "Pop", .Interprete = "Simply Red", .Titulo = "Sunrise", .Precio = 320})

        lobjDiscos.Add(New Disco With {.Id = 5, .Genero = "Rock", .Interprete = "Guns n Roses", .Titulo = "Use your ilution", .Precio = 220})

        lobjDiscos.Add(New Disco With {.Id = 6, .Genero = "Dance", .Interprete = "Gigi Dagostino", .Titulo = "L amour tojours", .Precio = 99})

        lobjDiscos.Add(New Disco With {.Id = 7, .Genero = "Clasica", .Interprete = "Haendel", .Titulo = "Mesias", .Precio = 410})

        lobjDiscos.Add(New Disco With {.Id = 8, .Genero = "Hip Hop", .Interprete = "Linkin Park", .Titulo = "Meteora", .Precio = 60})

 

 

        Dim lobjDiscosSeleccionados = From lobjSeleccionDiscos In lobjDiscos _

                  Where lobjSeleccionDiscos.Precio > 300 _

                  Order By lobjSeleccionDiscos.Titulo Ascending _

                  Select lobjSeleccionDiscos.Titulo, lobjSeleccionDiscos.Precio

 

 

        For Each lobjDisc In lobjDiscosSeleccionados

            MessageBox.Show(lobjDisc.Titulo.ToString() + " - " + lobjDisc.Precio.ToString())

        Next

 

 

 

 

Asimismo también tenemos LINQ to dataSet que como ustedes se pueden imaginar nos permite ejecutar  queries  is a través de las estructuras DataSet the que ofrece. Net.  Con esto podemos eliminar desde luego el uso del objeto DataView que se montaba sobre un dataSet y que nos permitía realizar funcionalidades equivalentes a un motor de base de datos como el ordenamiento o el filtrado de los datos de acuerdo a sentencias específicas ahora podemos utilizar LINQ directamente para extraer la información deseada.

 

También tenemos LINQ to XML donde es posible generar un query a partir de la declaración de un árbol XML, LINQ to SQL que nos permite (pronto un artículo sobre esto) generar objetos basándonos en la definición de una base de datos relacional (un ORM con esteroides) y LINQ to Entities, una tecnología que estará disponible en el futuro cercano cuyo objetivo es poner una capa intermedia de a basada en XML donde se defina la estructura y mapeo de los datos además de que contará con soporte a múltiples proveedores de base de datos

 

6) Expresiones lambda y conceptos sobre la programación funcional

 

El lenguaje de programación C# se está convirtiendo en un lenguaje de programación funcional.

La programación funcional es un paradigma de la misma manera que lo es el paradigma orientado objetos o la programación imperativa.

Existen lenguajes con enfoque el paradigma funcional desde hace ya bastante rato, el ejemplo principal es Haskell.

Así como en la programación orientada a objetos se tiene como objetivo primero describirle el mundo a la computadora mediante las clases y luego resolver el algoritmo mediante la interacción (relaciones) entre los objetos, el objetivo de la programación funcional es establecer “relaciones de igualdad” (de la misma manera que sucede en las ecuaciones matemáticas).

En la programación funcional debemos pensar que todo es una función y que el problema se resolverá mediante la generación de funciones y su descomposición en otras funciones más simples, o bien al revés, que podemos encontrar la solución a un problema componiendo funciones de funciones  y evaluando expresiones que resultan de la invocación de las mismas funciones. ¿Suena enredado? Para nada, es más fácil de lo que se puedan imaginar.

Por ejemplo, sabemos que el doble de un numero x será x+x. Utilizando la sintaxis de C# tenemos .

(En el siguiente ejemplo usamos expresiones lambda, para más detalle ver este artículo)

 

C#

Doble x = (int y) => y + y;

MessageBox.Show(x(2).ToString());

 

El resultado será 4

 

Así mismo sabemos que el cuádruple del mismo número será el doble del doble, en lugar de generar otro método para definirlo, podemos hacer uso de la inferencia de tipos que es básica en cualquier lenguaje de programación funcional y escribir lo siguiente (y que desde luego C# y VB la implementan)

 

 

   var Cuadruple = x(x(2));

 

// o bien

 

   var Cuadruple =  x(2) + x(2) ;

  MessageBox.Show(Cuadruple.ToString());

 

El resultado será 8

 

Y desde luego, si queremos saber el óctuple…

 

    var Octuple = Cuadruple+Cuadruple;

            MessageBox.Show(Octuple.ToString());

 

El resultado será 16.

 

Como podemos ver ya no estamos escribiendo más definiciones de funciones ni creando su cuerpo, simplemente estamos haciendo referencia mediante inferencia de tipos a una función que creamos al principio, como podemos ver esto se traduce en un aumento de la productividad del programador porque a resumidas cuentas nos estamos ahorrando una gran cantidad de código.

El soporte que tiene C#  para expresiones lambda (la base de la programación funcional) es mucho mejor que el que existe en VB  (por ejemplo, en VB las expresiones lambda deben ser expresiones que generen valores y no pueden ser sentencias, es decir no podemos crear una variable local dentro del cuerpo de una expresión lambda, cosa que sí se puede con C#) y con el futuro seguramente este soporte será ampliado.

Por su parte el equipo de VB ha decidido unir el destino del veterano VB al destino de la programación en xml con características como XML Literals (ver más abajo para más detalle).

Muchos programadores en C# quizá se sientan algo desilusionados debido a que el soporte en xml ahora es muchísimo más exhaustivo en visual basic que en C#, sin embargo creo que la decisión del equipo de C# tiene mucha lógica y se fundamenta en que las tecnologías alrededor de los lenguajes son efímeras. No sabemos que pueda suceder en el futuro con el XML, sobre todo cuando vienen nuevos como Astoria o Jasper (esperen un artículo de esto en enero). ¿Seguirá siendo válido el XML en 2 años? ¿En 5? ¿En 15?. Eso nadie lo sabe así que en C# se prefiere una filosofía más orientada al lenguaje puro alejándolo de las cosas alrededor.

 

7) Literales XML (Sólo VB)

Como les estaba comentando hace unas líneas el soporte a XML que integra visual basic es mucho mayor al que integra C#. Sin ir más lejos o simplemente examinen este código, no hay mucho que explicar

 

VB

 

        Dim lobjXML = <Peliculas>

                          <Pelicula>

                              <Titulo>El Exorcista</Titulo>

                              <Director>Juanito Perez</Director>

                              <Genero>Horror</Genero>

                          </Pelicula>

                          <Pelicula>

                              <Titulo>Saw 2 El juego del miedo</Titulo>

                              <Director>Juanito Perez</Director>

                              <Genero>Terror</Genero>

                          </Pelicula>

                          <Pelicula>

                              <Titulo>Silent Hill</Titulo>

                              <Director>XXX Perez</Director>

                              <Genero>Suspenso</Genero>

                          </Pelicula>

                      </Peliculas>

 

 

        MessageBox.Show(lobjXML.Elements.Count().ToString)

 

        For Each lobjElemento As XElement In lobjXML.Elements

            MsgBox(lobjElemento.Value())

        Next

 

Como ustedes pueden ver automáticamente el compilador reconoce cualquier declaración en xml

Y a partir de ella genera los objetos correspondientes para que no podamos programar programa ticamente sin necesidad de utilizar clases como XMLDocument. El código anterior nos muestra una bonita caja de texto con los valores que se encuentran dentro del fragmento xml. Esto la verdad es sorprendente, y se le denomina Literal Expression, ¡El XML ES el lenguaje de programación, es parte íntegra de VB!

 

Inclusive si no queremos utilizar el For Each podemos escribir un query y seleccionar aquellas películas que nos gusten mua ja ja…

 

VB

 

 

  Dim SeleccionXML = From Elemento In lobjXML.<Pelicula> _

                           Where Elemento.<Titulo>.Value = "Silent Hill" _

                           Select Elemento.<Genero>

 

        MsgBox(SeleccionXML.First.Value)

 

    Este código nos mostrará la palabra Suspenso. Y si queremos es todavía más allá es posible generar XML que tenía como contenido en lugar de valores estáticos variables o propiedades de objetos, sintaxis que seguramente les parecerá familiar

 

 

        Dim lobjXMLHoras = <Horas>

 

                               <Hora><Pais>México</Pais><HoraExacta><%= Now %></HoraExacta></Hora>

                               <Hora><Pais>Japón</Pais><HoraExacta><%= Now.AddHours(6) %></HoraExacta></Hora>

 

                           </Horas>

 

Del ejemplo anterior hemos puesto como valores el elemento HoraExacta al cálculo de la hora actual y en el caso del segundo elemento estamos añadiendo unas horas para representar un cálculo.

Algo que no puedo dejar de mencionar y que es medio horrible es que no es posible de debuggear las expresiones cuery en la ventana de immed. Esperemos que en próximas revisiones nuestros compas en Microsoft  le den un vistazo esto porque se puede volver un feo dolor de cabeza a la hora de programar cueris complejos. (Si pudieron con las nested master pages, que no puedan con esto juar juar)

 

“Query expressions are not valid in debug windows”

 

 

 

8) Operador ternario(Sólo VB)

Por todos es conocido que es posible representar un If en C# de la siguiente manera

C#


a%b==0 ? "Par" : "Non";

 

A pesar de que las versiones anteriores de visual basic o tenían una función llamada Iif, esta sintaxis era exactamente eso: una función por lo cual si alguno de las expresiones que se le pasaban esta función era inválida tronaba toda nuestra rutina. Como buena noticia ya ningun programador en C# se podrá burlar de los visualeros. Les presento al poderosísimo operador ternario en VB:

VB

 

If(lintNumero Mod 2 = 0, "Par", "Non")

 

 

 

9) Propiedades autoimplementadas (Sólo C#)

 

Sabemos nosotros que cuando estamos utilizando propiedades siempre es indispensable utilizar una variable privada dentro de la clase que se encargue de mantener el Valor que está expuesto por la propiedad en la versión 2005 de visual studio se introdujo el concepto de Refactoring que mediante el IDE nos permitía generar automáticamente estas variables, ahora esto se llevado a nivel de lenguaje y es posible generar implícitamente la variable privada que contendrá el tipo utilizando la siguiente sintaxis.

 

C#

 

public string Disquera {get; set;}

 

 

Bien, ahora sí, a esperar el año nuevo y fuera de coto, mis mejores deseos para el 2008, gracias por seguir entrando a DevelopersDotNet y les aseguro que en el 2008 este blog tratará, como lo ha intentado desde su creación de poner cosas, aunque sea medianamente originales y que aporten valor a este horrible pero genial armatoste llamado Internet.

 

Un abrazo a tod@s y

¡Feliz codificación!

Posted: 12-31-2007 7:53 AM por Bichi | con 1 comment(s) |
Nuevas tendencias en el acceso a datos

Hola como están los invito a descargar la presentación de la conferencia que di en el congreso Software Gurú de este año (todavía 2007 jeje)

http://www.sg.com.mx/sg07/presentaciones/Herramientas%20y%20tecnologias/SG07.T05.TendenciasDataAccess.pdf

 Encontrarán conceptos interesantes que espero estar expandiendo próximamente.

Saludos a to2