Más con respecto a un método extensor ForEach<T>

 

Algún tiempo después de que diera mi opinión sobre un potencial método extensor ForEach<T> en este post, tengo el gusto de recomendar a los lectores lo que ha escrito recientemente sobre el tema en su blog Eric Lippert, miembro del equipo de diseño de C# y sin duda alguna una de las mentes más sagaces de todo el equipo de lenguajes de Microsoft. Según todo parece indicar, no veremos un método como ése en la BCL en un futuro cercano. Yo, la verdad, no lo necesito.

Respuestas a mi plegaria?

“We’ve got to hold on to what we got
‘Cause it doesn´t make a difference if we make it or not…”
(“Livin’ on a prayer”, Bon Jovi, 1986)

Hace unos meses, al anunciarse la lista de características de Windows 7 y el contenido del Windows 7 SDK, rogaba por la sincronización de la salida de las versiones de .NET Framework con las de Windows, de modo que los programadores de código manejado no quedemos en desventaja frente a los de código nativo a la hora de acceder a las nuevas posibilidades que el sistema operativo pone a nuestra disposición. Esta vez es obvio que eso no se va a cumplir, pero al menos contemplo con satisfacción que empiezan a publicarse recursos para facilitarnos la labor a los programadores .NET.

Aquí os dejo los enlaces a tres entradas de code.msdn.microsoft.com en los que podréis obtener información y ejemplos de código relacionados con el aprovechamiento de las novedades más importantes de Windows 7 desde aplicaciones .NET:

Tendremos que aprovechar lo que hay (como sugiere la referencia musical de hoy), aún a expensas de que en un futuro próximo se incorporen a .NET librerías que cubran estas áreas y conviertan en redundante nuestro trabajo. Aunque nada nuevo hay bajo el sol: esto ya nos ha ocurrido anteriormente. El puerto serie o las canalizaciones (pipes) son dos ejemplos rápidos que me vienen a la mente.


Pop/rock tip: Jon Bon Jovi (New Jersey, 1962) ha sido una de las personalidades más destacadas del rock desde mediados de los ’80. Su banda, Bon Jovi, ha colocado sistemáticamente sus discos en lo más alto de las listas a lo largo de estas tres décadas, empezando con “Slippery when wet” (1986), al que pertenece el single al que hemos hecho referencia hoy, y hasta “Lost Highway” (2007), su último trabajo hasta el momento.

¿Qué problema tiene este código? (II-R)

“Mama always told me not to look into the sights of the sun
But, mama, that’s where the fun is…”
(“Blinded by the light”, The Manfred Mann’s Earth Band, 1976)

Bueno, la respuesta al puzle de ayer ya prácticamente la han dado los que han opinado, así que solo me queda hacer algunas puntualizaciones.

El programa propuesto es un ejemplo de cómo las expresiones lambda pueden acceder a las variables del contexto en el que son definidas. Estas variables se dice que son capturadas por la expresión lambda. Me ha gustado la explicación que ha dado jmservera de por qué el programa, en la versión que se presenta, imprimirá (64, 64, 64, 64, 64, 64) en vez de la secuencia deseada (1, 2, 4, 8, 16, 32). Ciertamente, creo que puede facilitarle bastante a un principiante la comprensión de cómo funciona el mecanismo de captura: está claro que en el primer bucle lo que se hace es definir las funciones lambda, mientras que éstas son llamadas (se ejecutan) en el segundo bucle, cuando la variable capturada (la i del primer bucle) vale 6, puesto que ese bucle ya ha terminado. No obstante, creo sumamente conveniente complementar esa explicación intuitiva con una presentación detallada de cómo el compilador de C# implementa las capturas, algo que no explicaré aquí, sino que me permitiré dirigir al lector a mi libro “C# 3.0 y LINQ“, donde se muestra, con la ayuda de Reflector, cómo esa implementación se lleva a cabo (OJO: en el capítulo “Métodos anónimos”, que antecede al dedicado a las expresiones lambda).

Obsérvese cómo si se introduce en el primer bucle una variable local, como propone Avalon, el codigo funcionará correctamente: cada expresión lambda capturará la copia correspondiente de esa variable. Recuérdese que las variables locales como la j de abajo “nacen” cuando la ejecución entra en el bloque en el que están definidas, y que serán copias diferentes para cada iteración. Otra cosa es que esas variables locales técnicamente mueren al terminar cada una de las iteraciones, pero el mecanismo de captura se encarga de cierta manera de “alargarles la vida” artificialmente (de modo similar a como hacían los soviéticos con los secretarios generales del PCUS :-).

        {
            // Create array of ‘power’ functions
            var powers = Func<int, int>[MAX_POWER];
            for (int i = 0; i < MAX_POWER; i++)
            {
                int j = i;  // variable local que se crea e inicializa
                               // para cada iteración
                powers[j] = x => (int) Math.Round(Math.Pow(x, j));
            }

            // …
        }

Como se habrá dado cuenta el lector, el mecanismo de captura de variables (sumamente útil en la práctica, como creo que se demuestra en mi libro y en muchas otras fuentes) presenta sutilezas que hay que tener bien claras para que no “nos pille el toro”. ¡Queda advertido!


Pop/rock tip: Manfred Mann es un músico sudafricano afincado en Londres que formó parte de la escena del pop/rock desde principios de los ’60. El éxito mundial, sin embargo, no le llegó hasta 1976, gracias a una versión en clave de rock de una balada de Bruce Springsteen que había pasado originalmente desapercibida, “Blinded by the light“. Era la época en que yo seguía fielmente todos los domingos el American Top Forty a través de la emisora WGBS de Miami; actividad que, además del placer que me proporcionaba la música en sí, tenía el sublime atractivo de lo clandestino: al escuchar ese programa yo estaba incurriendo en “diversionismo ideológico”, el término revolucionario con el que se denominaba entonces al consumo de los “productos culturales del enemigo”. ¡La de gilipolleces de que está llena la historia de la humanidad!

Qué problema tiene este código? (II)

“Captured by the moment
In the magic of a yesterday
Captured by the moment
And I hope it never fades away”
(“Captured by the moment”, Steve Perry, 1984)

Aquí va otro puzle del que seguramente algunos ya sabrán la respuesta, pero espero que a otros les enseñe algo nuevo. Se me ocurrió presentarlo aquí después de leer la reciente (y excelente) serie de posts sobre las expresiones lambda de José M. Aguilar.

El siguiente programa intenta calcular las potencias de 2 (1, 2, 4, 16, 32, etc.) utilizando un array de funciones lambda para elevar a cada una de las potencias. Pero… ¿consigue su objetivo? La respuesta (la letra de la canción contiene, por supuesto, una pista) – en una próxima entrega.

using System;

namespace ConsoleApplication1
{
    class Program
    {
        const int MAX_POWER = 6;

        static void Main(string[] args)
        {
            // Create array of ‘power’ functions
            var powers = Func<int, int>[MAX_POWER];
            for (int i = 0; i < MAX_POWER; i++)
                powers[i] = x => (int) Math.Round(Math.Pow(x, i));

            // Print powers of 2
            for (int i = 0; i < MAX_POWER; i++)
                Console.WriteLine(powers[i](2));
        }
    }
}


Pop/rock tip: Journey fue una de las bandas de rock más populares de Norteamérica durante finales de los ’70 y la década de los ’80. Temas suyos como “Don’t stop believing” siguen apareciendo frecuentemente en la radio y la televisión (por ejemplo, la serie “Los Soprano“) y utilizándose en eventos deportivos (sobre todo cuando el equipo local va perdiendo :-). Un elemento distintivo de la música de Journey fue siempre la espectacular voz de su cantante Steve Perry, que paralelamente a su trabajo con la banda hizo su debut en solitario con el exitoso álbum “Street Talk” (1984), al que pertenece a canción que hemos utilizado aquí.

Por cierto, Journey aún sigue “dando guerra”, y el pasado verano pudimos verlos en Madrid ahora con otro cantante, Arnel Pineda, cuya voz se parece bastante a la de Perry.